Количество узлов и происшествий - XSL - PullRequest
3 голосов
/ 01 октября 2009

Мне нужно написать общий xsl, который будет принимать XML-документ и выводить количество узлов и их имен. Так что, если у меня есть файл, подобный следующему:

   <assets>
    <asset>
        <type>hardware</type>
        <item>
            <name>HP laptop</name>
            <value>799</value>
        </item>
        <item>
            <name>server</name>
            <value>1000</value>
        </item>
        <item>
            <name>ViewSonic Monitor</name>
            <value>399</value>
        </item>
    </asset>
    <asset>
        <type>software</type>
        <item>
            <name>Windows Vista</name>
            <value>399</value>
        </item>
        <item>
            <name>Office XP</name>
            <value>499</value>
        </item>
        <item>
            <name>Windows 7</name>
            <value>399</value>
        </item>
          <item>
            <name>MS Project Professional 2007</name>
            <value>299</value>
          </item>
       </asset>
    </assets>

Вывод будет:

   <output>
    <node name="assets" count="1"/>
    <node name="asset" count="2"/>
    <node name= "type" count="??"/>
    <node name="item" count=??/>
    <node name="name" count=??/>
    <node name="value" count=??/>
    </output>

Ответы [ 3 ]

6 голосов
/ 01 октября 2009

Вы хотите использовать функцию подсчета:

<xsl:value-of select="count(assets/asset)" />

Ваш код будет выглядеть так:

Assets: <xsl:value-of select="count(assets)" />
Asset:  <xsl:value-of select="count(assets/asset)" />
Item:   <xsl:value-of select="count(assets/asset/item)" />
4 голосов
/ 01 октября 2009

Общее решение для ввода, содержащее узлы с любыми именами, может быть выполнено с использованием метода Muenchian :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="nodes-by-name" match="*" use="name()"/>
  <xsl:template match="/">
    <output>
      <xsl:for-each select="//*[count(.|key('nodes-by-name', name())[1]) = 1]">
        <node name="{name()}" count="{count(key('nodes-by-name', name()))}"/>
      </xsl:for-each>
    </output>
  </xsl:template>
</xsl:stylesheet>

Объяснение: Используя xsl:key, создайте отображение из имен в узлы, имеющие это имя. Затем выполните итерацию по всем уникальным именам и выведите количество узлов для имени. Основной трюк здесь - как перебирать уникальные имена. См. Связанную страницу для объяснения идиомы count(.|foo)=1, используемой для выяснения, является ли foo набором узлов, содержащим только узел контекста.

1 голос
/ 13 февраля 2016

Это мое решение с использованием XSLT 2.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/">
      <xsl:element name="output">
         <xsl:for-each-group select="//*" group-by="name()">
            <xsl:element name="node">
               <xsl:attribute name="name">
                  <xsl:value-of select="current-grouping-key()"/>
               </xsl:attribute>
               <xsl:attribute name="count">
                  <xsl:value-of select="count(current-group())"/>
               </xsl:attribute>
            </xsl:element>
         </xsl:for-each-group>
      </xsl:element>
   </xsl:template>

</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...