XSLT с подсчетом элементов с заданным значением

мне нужно подсчитать количество элементов в XML-файле, которые имеют определенное значение (для проверки уникальности). XML-файл выглядит следующим образом:

EDIT: я обновил оригинальный" упрощенный " 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>

Я пытаюсь определить переменную, чтобы увидеть, сколько свойств на живом / Мертвом уровне имейте длинное значение (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". Но я уверен, что могу рассчитывать только на один элемент свойства ("Value") под "ID" и только на один "длинный" элемент под "Value".

[отказ от ответственности] тот, кто разработал общий XML-файл, с которым я застрял, действительно не знал, как структурировать XML (например, назад использование атрибутов против элементов). Я боюсь, что мое мышление XSLT временно было искажено:) в результате. [/отказ от ответственности]

3 ответов


Это 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 и значения). Они не являются обязательными, так как вы можете прибыть на соответствующий узел, используя иерархию в XML. Кроме того, вы уже упоминали, что проверка уникальности основана только на содержимом long элемент.


ваш xpath немного выключен:

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

Edit: Cerebrus совершенно справедливо указывает, что код в вашем OP (используя неявное значение узла) абсолютно подходит для ваших целей. На самом деле, поскольку вполне вероятно, что вы хотите работать с узлом "свойство", а не с "длинным" узлом, это, вероятно,superior просить //Property[long=$parPropId] чем текст () xpath, хотя вы могли бы сделать дело для последнего на основании читаемости.

что я могу сказать, Я немного устал сегодня :)


<xsl:variable name="count" select="count(/Property/long = $parPropId)"/>

un-tested, но я думаю, что это должно работать. Я предполагаю, что узлы свойств являются прямыми дочерними узлами корневого узла и поэтому вынимают селектор потомков для peformance