【问题标题】:XSLT counting elements with a given valueXSLT 计算具有给定值的元素
【发布时间】:2023-03-22 02:57:02
【问题描述】:

我需要计算 XML 文件中具有特定值的元素的数量(以验证唯一性)。 XML 文件如下所示:

编辑:我用某人设计的实际毛茸茸的混乱更新了原始的“简化”XML。不幸的是,除非经过编辑,否则这将使之前的所有答案都变得非常混乱和错误。

<root>
  <ac>
   <Properties>
     <Property Name="Alive">
      <Properties>
        <Property Name="ID">
         <Properties>
           <Property Name="Value">
            <long>11007</long>
           </Property>
         </Properties>
        </Property>
      </Properties>
     </Property>
     <Property Name="Dead">
      <Properties>
        <Property Name="ID">
         <Properties>
           <Property Name="Value">
            <long>11008</long>
           </Property>
         </Properties>
        </Property>
      </Properties>
     </Property>
     ...
     <Property Name="MostlyDeadAllDay">
      <Properties>
        <Property Name="ID">
         <Properties>
           <Property Name="Value">
            <long>99001</long>
           </Property>
         </Properties>
        </Property>
      </Properties>
     </Property>
   </Properties>
  </ac>
</root>

我正在尝试定义一个变量,以查看有多少 Alive/Dead 级别的属性具有模板参数中定义的长值 (ID)。沿着这些思路(虽然我怀疑这是错误的)......

<xsl:param name="parPropId"/>
<xsl:variable name="countProperties">
   <xsl:value-of select="count(/root/ac/
      Properties/Property/
      Properties/Property[@Name = 'ID']/
      Properites/Property[@Name = 'Value']/long = $parPropId)"/>
</xsl:variable>

在“ID”级别可以定义多个 Property 元素。但我相当肯定我只能指望“ID”下的一个 Property 元素(“Value”),以及“Value”下的一个“long”元素。

[免责声明] 设计整个 XML 文件的人确实不知道如何构建 XML(例如,向后使用属性与元素)。我担心我的 XSLT 想法因此暂时被扭曲了 :)。 [/免责声明]

【问题讨论】:

  • 为什么您显示的 XPath 表达式“错误”?我看不出有什么问题。
  • 不确定。我简化了上面的 XML。实际的 xpath 是这样的:“///Properties/Property/Properties/Property[@Name = 'ID']/Properties/Property[@Name = 'Value']/long”。如果你是正确的,我可以用“[long = $parPropId]”替换“/long”。似乎是错误的,因为这会将两个“[]”操作放在一起。
  • 我验证了 vartec 的 text() 给出了正确的文本(即“///Properties/Property/Properties/Property[@Name = 'ID']/Properties/Property[@Name = 'Value ']/long/text()" 获取了我的 ID,但我使用他的方法计数仍然失败。
  • 我也尝试过“count(...Property[(@Name = 'Value') and (long/text() = $parPropId)])”,但总是返回 0。我想想艾德定律,“行为越离奇,错误越愚蠢”在这里充分发挥了作用。
  • 似乎我们在这里缺少的是您实际 XML 的横截面。如果我们看到我们究竟要查询什么,答案可能会更准确。我建议编辑您的答案并替换“简化的”XML sn-p。

标签: xslt count elements


【解决方案1】:

这个 XPath:

count(//Property[long = '11007'])

返回与以下相同的值:

count(//Property/long[text() = '11007'])

...除了第一个计数Property 匹配条件的节点,第二个计数long 匹配条件的子节点。

根据您的评论和多次阅读您的问题,我相信您希望根据标准组合找到独特性。因此,实际上,我认为您实际上是在检查多个条件。以下方法也可以:

count(//Property[@Name = 'Alive'][long = '11007'])

因为它的含义与:

count(//Property[@Name = 'Alive' and long = '11007'])

当然,您可以用这些值替换模板中的参数。上面的代码只是说明了这一点。

编辑(问题编辑后)


关于 XML 很糟糕,您说得很对。事实上,这是一个彻头彻尾的CodingHorror 候选人!我不得不不断地重新计算以跟踪我目前所在的“属性”节点。我感觉到你的痛苦!

给你:

count(/root/ac/Properties/Property[Properties/Property/Properties/Property/long = $parPropId])

请注意,我已删除所有其他检查(针对 ID 和 Value)。它们似乎不是必需的,因为您可以使用 XML 中的层次结构到达相关节点。另外,您已经提到唯一性检查仅基于 long 元素的内容。

【讨论】:

  • 感谢您教育我了解此 xpath 等效性!你们所说的一切都很有道理(基于我适度的 XSL/XPath 经验)。实际上,我没有多个条件,我只关心 ID。只是无法获得该计数来给出非零值 [arrrgghh]。
  • 令人惊讶的是,这些小丑有时使用 'string' 和 'int' 而不仅仅是 'long' 来表示这些 ID。你让我有动力提交给 CodingHorror!我最终删除了解决方案的“/long”部分(现在可以使用)。我将此标记为答案,并感谢一百万对我的包容。
【解决方案2】:

您的 xpath 有点偏离:

count(//Property/long[text()=$parPropId])

编辑:Cerebrus 非常正确地指出,您的 OP 中的代码(使用节点的隐式值)绝对适合您的目的。事实上,由于您很可能希望使用“Property”节点而不是“long”节点,因此请求//Property[long=$parPropId] 可能比 text() xpath 更优越,尽管你出于可读性的考虑,可以为后者提供理由。

我能说什么,我今天有点累:)

【讨论】:

  • 猜猜看!您现在有 666 个答案!意义重大!
  • 完全巧合的是,Dimitre 又回到了他的十字军东征中。
  • 并非巧合的是,Annakata 再次删除了任何解释他/她的答案真正错误的评论。
  • 是的,我确实遇到了一个问题,即没有提供 200 行响应,这些响应无法覆盖 0.01% 的边缘情况,以防提问者无法进行智能分析。你是英雄迪米特里。
  • 有时你的答案比不覆盖 0.01% 的边缘情况更糟糕。你最大的失败是你不接受批评,也不用批评来改进。如果任何答案有问题,我都会做出反应。回答不是收集代表的仓促工作。删除这个棘手的评论? :)
【解决方案3】:
<xsl:variable name="count" select="count(/Property/long = $parPropId)"/>

未经测试,但我认为应该可以。我假设属性节点是根节点的直接子节点,因此取出你的后代选择器以获得性能

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 2021-10-23
    相关资源
    最近更新 更多