XSLT统计xsl:for-each内xsl:choose执行次数及无匹配输出默认值
XSLT匹配提取及默认值实现问题
我需要提取所有匹配的ttype和vendor.id,匹配规则为:assemblyCustom/revisionCustom/entityTypeCode 和 assemblyCustom/revisionCustom/usCode 分别与任意 ttypes-config/item/enityTypeCode/ 和 ttypes-config/item/usCode 的值匹配。
输入XML
<?xml version="1.0" encoding="UTF-8"?> <combined-xml> <assemblyCustom> <revisionCustom> <entityTypeCode>C</entityTypeCode> <usCode>G</usCode> </revisionCustom> </assemblyCustom> <ttypes-config> <item> <vendor.id>111</vendor.id> <ttype>AAA</ttype> <enityTypeCode> <item>C</item> <item>D</item> <item>E</item> <item>F</item> </enityTypeCode> <usCode> <item>G</item> <item>H</item> <item>I</item> <item>J</item> <item>K</item> <item>L</item> <item>M</item> </usCode> </item> <item> <vendor.id>222</vendor.id> <ttype>BBB</ttype> <enityTypeCode> <item>N</item> <item>C</item> </enityTypeCode> <usCode> <item>G</item> </usCode> </item> <item> <vendor.id>333</vendor.id> <ttype>CCC</ttype> <enityTypeCode> <item>Q</item> <item>R</item> </enityTypeCode> <usCode> <item>S</item> </usCode> </item> <item> <vendor.id>444</vendor.id> <ttype>DDD</ttype> <enityTypeCode> <item>T</item> <item>U</item> </enityTypeCode> <usCode> <item>V</item> </usCode> </item> <item> <vendor.id>555</vendor.id> <ttype>EEEs</ttype> <enityTypeCode> <item>W</item> </enityTypeCode> <usCode> <item>X</item> <item>Y</item> </usCode> </item> </ttypes-config> </combined-xml>
期望输出
匹配成功时
<?xml version="1.0" encoding="UTF-8"?> <ttype-output> <ttype>AAA</ttype> <vendor.id>111</vendor.id> <ttype>BBB</ttype> <vendor.id>222</vendor.id> </ttype-output>
无匹配时
<?xml version="1.0" encoding="UTF-8"?> <ttype-output> <ttype>Default</ttype> <vendor.id>000</vendor.id> </ttype-output>
当前已实现的XSL代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:variable name="entityTypeCode"> <xsl:value-of select="combined-xml/assemblyCustom/revisionCustom/entityTypeCode"/> </xsl:variable> <xsl:variable name="usCode"> <xsl:value-of select="combined-xml/assemblyCustom/revisionCustom/usCode"/> </xsl:variable> <xsl:template match="/combined-xml/ttypes-config/item"> <xsl:variable name="current_entityTypeCode"> <xsl:value-of select="enityTypeCode"/> </xsl:variable> <xsl:variable name="current_usCode"> <xsl:value-of select="usCode"/> </xsl:variable> <xsl:if test="contains($current_entityTypeCode, $entityTypeCode) and contains($current_usCode, $usCode)"> <ttype> <xsl:value-of select="ttype"/> </ttype> <vendor.id> <xsl:value-of select="vendor.id"/> </vendor.id> </xsl:if> </xsl:template> <xsl:template match="/"> <ttype-output> <xsl:apply-templates select="/combined-xml/ttypes-config/item"></xsl:apply-templates> </ttype-output> </xsl:template> </xsl:stylesheet>
待解决的问题
- 如何统计xsl:for-each语句内xsl:choose的执行次数?
- 如何添加xsl:otherwise逻辑,实现只有当所有循环迭代都不满足条件时才输出默认ttype?
解决方案
先修正现有匹配逻辑的问题
你当前用contains()判断存在逻辑漏洞:如果enityTypeCode/item存在值为CA的项,匹配C时也会被误命中。建议直接判断是否存在相等的子项,匹配条件修改为:
<xsl:if test="enityTypeCode/item[text()=$entityTypeCode] and usCode/item[text()=$usCode]">
问题1:统计xsl:for-each内xsl:choose的执行次数
XSLT是函数式语言,变量赋值后不可变,你可以通过以下方式统计:
- 如果是XSLT 2.0及以上版本,直接统计符合条件的节点数即可:
<xsl:variable name="matchCount" select="count(/combined-xml/ttypes-config/item[enityTypeCode/item/text()=$entityTypeCode and usCode/item/text()=$usCode])"/> - 如果是XSLT 1.0,也可以先把匹配到的节点存入节点集变量,再统计数量:
<xsl:variable name="matchedItems" select="/combined-xml/ttypes-config/item[enityTypeCode/item/text()=$entityTypeCode and usCode/item/text()=$usCode]"/> <xsl:variable name="matchCount" select="count($matchedItems)"/>
你所说的xsl:choose执行次数本质就是循环的item总数,直接用count(/combined-xml/ttypes-config/item)就能获取。
问题2:实现无匹配时输出默认值
你可以先把匹配到的内容存入变量,判断匹配数量是否为0,再输出默认值即可。以下是修改后的完整XSL代码:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:variable name="entityTypeCode" select="combined-xml/assemblyCustom/revisionCustom/entityTypeCode"/> <xsl:variable name="usCode" select="combined-xml/assemblyCustom/revisionCustom/usCode"/> <!-- 先筛选所有匹配的item --> <xsl:variable name="matchedItems" select="/combined-xml/ttypes-config/item[enityTypeCode/item/text()=$entityTypeCode and usCode/item/text()=$usCode]"/> <xsl:template match="item" mode="output"> <ttype> <xsl:value-of select="ttype"/> </ttype> <vendor.id> <xsl:value-of select="vendor.id"/> </vendor.id> </xsl:template> <xsl:template match="/"> <ttype-output> <xsl:choose> <!-- 有匹配项时输出所有匹配结果 --> <xsl:when test="$matchedItems"> <xsl:apply-templates select="$matchedItems" mode="output"/> </xsl:when> <!-- 无匹配时输出默认值 --> <xsl:otherwise> <ttype>Default</ttype> <vendor.id>000</vendor.id> </xsl:otherwise> </xsl:choose> </ttype-output> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者Anuj Parmar
相关产品推荐
相关产品推荐

