【问题标题】:XSLT 2 | For-Each Alternative | When Using doc()XSLT 2 |对于每个选择 |使用 doc() 时
【发布时间】:2020-06-19 06:28:06
【问题描述】:

我一直在尝试转变:

...以下内容:[CSKS 文档]

<ZRFC_READ_TABLE.Response>
    <DATA>
        <item>
            <WA>20200306~99999999~123456~EUR  ~6000~1234~HELO      ~ ~</WA>
        </item>
        <item>
            <WA>20200306~99999999~789012~EUR  ~6000~1234~HEYL      ~ ~</WA>
        </item>
        <item>
            <WA>20200306~99999999~345678~EUR  ~6000~1234~HIYA      ~ ~</WA>
        </item>
    </DATA>
</ZRFC_READ_TABLE.Response>

将以下内容作为查找源:[CSKT doc]

<ZRFC_READ_TABLE.Response>
    <DATA>
        <item>
            <WA>123456~This is a test message 1~</WA>
        </item>
        <item>
            <WA>789012~This is a test message 2~</WA>
        </item>
        <item>
            <WA>345678~This is a test message 3~</WA>
        </item>
    </DATA>
</ZRFC_READ_TABLE.Response>

使用以下 XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="CSKT_FilePath"/>
    <xsl:param name="CSKS_FilePath"/>
    <xsl:template match="/">
        <xsl:element name="masterData">
            <xsl:choose>
                <xsl:when test="(not($CSKT_FilePath) and not(string($CSKT_FilePath))) and (not($CSKS_FilePath) and not(string($CSKS_FilePath)))">
                    <xsl:message terminate="yes">One or more Input Parameter(s) not supplied!</xsl:message>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="CSKTData" select="doc($CSKT_FilePath)"/>
                    <xsl:variable name="CSKSData" select="doc($CSKS_FilePath)"/>
                    <xsl:variable name="ReplaceFunction">
                        <ReplaceFunction name="LTEXT BY KOSTL">
                            <xsl:for-each select="$CSKTData/ZRFC_READ_TABLE.Response/DATA/item/WA">
                                <xsl:element name="item">
                                    <xsl:attribute name="key" select="replace(normalize-space(tokenize(., '~')[1]), '[^0-9a-zA-Z]+', '')"/>
                                    <!--<xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text>-->
                                    <xsl:value-of select="normalize-space(tokenize(., '~')[2])"/>
                                    <!--<xsl:text disable-output-escaping="yes">]]&gt;</xsl:text>-->
                                </xsl:element>
                            </xsl:for-each>
                        </ReplaceFunction>
                    </xsl:variable>             
                    <xsl:for-each select="$CSKSData/ZRFC_READ_TABLE.Response/DATA/item/WA">
                        <xsl:variable name="_ccDesc_In" select="replace(normalize-space(tokenize(., '~')[3]), '[^0-9a-zA-Z]+', '')"/>
                        <mdRec>
                            <dateFrom>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[1])"/>
                            </dateFrom>
                            <dateTo>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[2])"/>
                            </dateTo>
                            <costCenter>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[3])"/>
                            </costCenter>
                            <cur>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[4])"/>
                            </cur>
                            <contArea>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[5])"/>
                            </contArea>
                            <compCode>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[6])"/>
                            </compCode>
                            <profitCenter>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[7])"/>
                            </profitCenter>
                            <lockInd>
                                <xsl:value-of select="normalize-space(tokenize(., '~')[8])"/>
                            </lockInd>
                            <ccDesc>
                                <xsl:value-of select="$ReplaceFunction//item[@key=$_ccDesc_In]/text()"/>
                            </ccDesc>
                        </mdRec>
                    </xsl:for-each>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

产生如下所需的输出:

<masterData>
    <mdRec>
        <dateFrom>20200306</dateFrom>
        <dateTo>99999999</dateTo>
        <costCenter>123456</costCenter>
        <cur>EUR</cur>
        <contArea>6000</contArea>
        <compCode>1234</compCode>
        <profitCenter>HELO</profitCenter>
        <lockInd/>
        <ccDesc>This is a test message 1</ccDesc>
    </mdRec>
    <mdRec>
        <dateFrom>20200306</dateFrom>
        <dateTo>99999999</dateTo>
        <costCenter>789012</costCenter>
        <cur>EUR</cur>
        <contArea>6000</contArea>
        <compCode>1234</compCode>
        <profitCenter>HEYL</profitCenter>
        <lockInd/>
        <ccDesc>This is a test message 2</ccDesc>
    </mdRec>
    <mdRec>
        <dateFrom>20200306</dateFrom>
        <dateTo>99999999</dateTo>
        <costCenter>345678</costCenter>
        <cur>EUR</cur>
        <contArea>6000</contArea>
        <compCode>1234</compCode>
        <profitCenter>HIYA</profitCenter>
        <lockInd/>
        <ccDesc>This is a test message 3</ccDesc>
    </mdRec>
</masterData>

这个,在CSKS文档中处理1000s[准确来说是50000]的WA子segment时,大概需要5-6分钟的时间进行转换。这可能是由于使用了 for-each 或构建不佳的 XSLT 本身。就性能而言,是否有更好的选择?

【问题讨论】:

  • 使用密钥或使用 XSLT/XPath 3 映射。
  • @MartinHonnen,谢谢,我确实看到了其他一些 SO 讨论,其中提出了 XSLT 3 映射,但我希望在 XSLT 2 中实现所需...

标签: xml xslt foreach xslt-2.0 lookup


【解决方案1】:

在 XSLT 中将键 &lt;xsl:key name="ltext-by-kostl" match="item" use="@key"/&gt; 声明为顶级元素(即 xsl:stylesheetxsl:transform 的子元素),然后使用 key('ltext-by-kostl', $_ccDesc_In, $ReplaceFunction) 代替 $ReplaceFunction//item[@key=$_ccDesc_In]/text()

如果您不进行所有这些 tokenize 调用,它也可能会提高性能,而是在可能的情况下仅使用该函数一次并将其结果存储在一个变量中,例如&lt;xsl:variable name="tokens" select="tokenize(...)"/&gt;,然后在需要的地方访问$tokens[1]$tokens[2]

【讨论】:

  • 这极大地提升了性能。谢谢你,@MartinHonnen。该操作现在耗时不到 30 秒。已接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 2020-01-18
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
相关资源
最近更新 更多