【问题标题】:Counting distinct items in XSLT independent of depth计算 XSLT 中的不同项目,与深度无关
【发布时间】:2010-07-15 14:53:25
【问题描述】:

如果我运行以下 XSLT 代码:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:key name="kValueByVal" match="variable_name/@value"
  use="."/>

 <xsl:template match="assessment">
  <xsl:for-each select="
   /*/*/variable/attributes/variable_name/@value
             [generate-id()
             =
              generate-id(key('kValueByVal', .)[1])
             ]
   ">
     <xsl:value-of select=
     "concat(., ' ', count(key('kValueByVal', .)), '&#xA;')"/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

在以下 XML 上:

<assessment>
    <variables>
        <variable>
            <attributes>
                <variable_name value="FRED"/>
            </attributes>
        </variable>
    </variables>
    <variables>
        <variable>
            <attributes>
                <variable_name value="MORTIMER"/>
            </attributes>
        </variable>
    </variables>
    <variables>
        <variable>
            <attributes>
                <variable_name value="FRED"/>
            </attributes>
        </variable>
    </variables>
</assessment>

我得到了想要的输出:

FRED 2
MORTIMER 1

(如果您愿意,请参阅my original question 了解更多信息。)

但是,如果我在这个输入上运行它:

<ExamStore>
    <assessment>
        <variables>
            <variable>
                <attributes>
                    <variable_name value="FRED"/>
                </attributes>
            </variable>
        </variables>
        <variables>
            <variable>
                <attributes>
                    <variable_name value="MORTIMER"/>
                </attributes>
            </variable>
        </variables>
        <variables>
            <variable>
                <attributes>
                    <variable_name value="FRED"/>
                </attributes>
            </variable>
        </variables>
    </assessment>
</ExamStore>

我什么也得不到。 (请注意,我只是将原始输入包装在一个 ExamStore 标记中。)我期待并希望得到相同的输出。

我为什么不呢?如何更改原始 XSLT 代码以获得相同的输出?

【问题讨论】:

  • +1 试图找出真相。请参阅我的回答,解释问题并提供解决方案。

标签: xslt counting distinct-values xslt-grouping


【解决方案1】:

那么您选择的 xpath /*/*/variable/attributes/variable_name/... 不再正确,因为您在节点树中添加了另一个更高的节点。

如果你想拥有真正的独立性,你需要使用类似的东西:

//variable/attributes/variable_name/...

...(不是开头的双斜杠),但这相当危险,因为它会捕获该结构的所有出现 - 请确保这就是您的意思。

否则,只需在您的 xpath 前面加上另一个 /*

【讨论】:

    【解决方案2】:

    当您在 XML 文档中引入另一个级别时,这搞砸了原始解决方案中使用的绝对 XPath 表达式(完全按照您的原始 XML 文件定制)。

    因此,为了使 XPath 表达式在新情况下工作,只需执行以下操作:

    替换

    /*/*/variable/attributes/variable_name/@value 
    

    /*/*/*/variable/attributes/variable_name/@value
    

    现在你又得到了想要的整洁结果:

    FRED 2
    MORTIMER 1
    

    我永远不会给你一个“独立”的解决方案,因为你没有提供任何关于你想要应用转换的可能 XML 文档集的属性/保证/约束。

    在您使用的原始问题中:

    .//variables/variable/attributes/variable_name
    

    关闭assessment

    这就是我在解决方案中使用绝对 XPath 表达式的原因。无法保证在另一个 XML 文档中某些 variable_name 元素不会存在,因此它们的祖先链不是 variables/variable/attributes,如果是这种情况,这意味着您可能对此类的值不感兴趣“不规则”variable_name 元素。

    教训是,在定义问题时不应过于具体,然后想要通用解决方案。 :)

    【讨论】:

      【解决方案3】:

      对于真正的结构独立你应该使用:

      <xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output method="text"/>
      
       <xsl:key name="kValueByVal" match="variable_name/@value"
        use="."/>
      
       <xsl:template match="variable_name[@value
                   [generate-id()
                   =
                    generate-id(key('kValueByVal', .)[1])
                   ]]">
           <xsl:value-of select=
           "concat(@value, ' ', count(key('kValueByVal', @value)), '&#xA;')"/>
       </xsl:template>
      </xsl:stylesheet>
      

      第一次输入的结果:

      FRED 2
      MORTIMER 1
      

      第二个输入的结果:

      FRED 2
      MORTIMER 1
      

      注意:切勿使用// 作为第一个 XPath 运算符。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-19
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        相关资源
        最近更新 更多