XSLT 2 | For-Each 备选方案 |使用 doc() 时
XSLT 2 | For-Each Alternative | When Using doc()
我一直在努力转型:
...以下内容:[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 文档]
<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"><![CDATA[</xsl:text>-->
<xsl:value-of select="normalize-space(tokenize(., '~')[2])"/>
<!--<xsl:text disable-output-escaping="yes">]]></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子段时,大概需要5-6分钟的时间进行转换。这可能是由于单独使用 for-each 或构建不当的 XSLT。就性能而言,是否有更好的选择?
在您的 XSLT 中将键 <xsl:key name="ltext-by-kostl" match="item" use="@key"/>
声明为顶级元素(即 xsl:stylesheet
或 xsl:transform
的子元素),然后使用 [=14 而不是 $ReplaceFunction//item[@key=$_ccDesc_In]/text()
=].
如果您不进行所有这些 tokenize
调用,而是在可能的情况下只使用该函数一次并将其结果存储在一个变量中,例如<xsl:variable name="tokens" select="tokenize(...)"/>
然后在需要的地方访问 $tokens[1]
、$tokens[2]
。
我一直在努力转型:
...以下内容:[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 文档]
<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"><![CDATA[</xsl:text>-->
<xsl:value-of select="normalize-space(tokenize(., '~')[2])"/>
<!--<xsl:text disable-output-escaping="yes">]]></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子段时,大概需要5-6分钟的时间进行转换。这可能是由于单独使用 for-each 或构建不当的 XSLT。就性能而言,是否有更好的选择?
在您的 XSLT 中将键 <xsl:key name="ltext-by-kostl" match="item" use="@key"/>
声明为顶级元素(即 xsl:stylesheet
或 xsl:transform
的子元素),然后使用 [=14 而不是 $ReplaceFunction//item[@key=$_ccDesc_In]/text()
=].
如果您不进行所有这些 tokenize
调用,而是在可能的情况下只使用该函数一次并将其结果存储在一个变量中,例如<xsl:variable name="tokens" select="tokenize(...)"/>
然后在需要的地方访问 $tokens[1]
、$tokens[2]
。