Подсчитайте количество вложенных дочерних элементов, используя XSLT - PullRequest
0 голосов
/ 12 сентября 2018

У меня есть следующий xml (который на самом деле является очень упрощенной версией словаря FIX):

<fix>
<messages>
    <message name='Message1'>
        <field name='Field1' />
        <component name='Component1'/>
        <group name='Group1'>
            <field name='Field2' />
        </group>
    </message>
</messages>

<components>
    <component name='Component1'>
        <field name='Field3' />
        <group name='Group2' >
                <field name='Field4' />
                <group name='Group3' >
                    <field name='Field5' />
                    <component name='Component3' />
                </group>
        </group>
        <component name='Component2' /> 
    </component>
    <component name='Component2'>
        <field name='Field6' />
    </component>
    <component name='Component3'>
        <field name='Field7'/>
    </component>  

</components>
<fields>
    .....
</fields>
</fix>

Каждое сообщение, компонент или группа могут иметь поля, компоненты и группы.

Мне нужно посчитать количество групп для каждого сообщения. В приведенном выше примере количество групп для сообщения 1 равно 3 (группа 1, группа 2, группа 3)

1 Ответ

0 голосов
/ 12 сентября 2018

Я предполагаю, что вы хотите сосчитать группы в элементах component, на которые есть ссылки, и, кроме того, элементы component, на которые есть ссылки в первом сообщении, сами могут ссылаться на другие элементы component с группами в.

В этом случае рекурсивная функция сделает свое дело.

Попробуйте это XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:my="myFunctions">

  <xsl:output method="text" />

  <xsl:key name="components" match="components/component" use="@name" />

  <xsl:template match="/">
    <xsl:apply-templates select="//message[@name='Message1']" />
  </xsl:template>

  <xsl:template match="message">
    <xsl:value-of select="my:groupCount(.)" />
  </xsl:template>

  <xsl:function name="my:groupCount">
    <xsl:param name="node" />
    <xsl:value-of select="count($node//group) + sum($node//component/my:groupCount(key('components', @name)))" />
  </xsl:function>

</xsl:stylesheet>

См. Это в действии на http://xsltfiddle.liberty -development.net / jyH9rMP

На самом деле, это не даст правильных результатов в компоненте 1 и компоненте 2, на который ссылается компонент 3 (в котором были группы), поскольку он будет учитывать одну и ту же группу дважды.

В этом случае попробуйте этот XSLT вместо

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

  <xsl:key name="components" match="components/component" use="@name" />

  <xsl:template match="/">
    <xsl:apply-templates select="//message[@name='Message1']" />
  </xsl:template>

  <xsl:template match="message">
    <xsl:value-of select="count(my:groups(.)/@name)" />
  </xsl:template>

  <xsl:function name="my:groups">
    <xsl:param name="node" />
    <xsl:sequence select="$node//group, $node//component/my:groups(key('components', @name))" />
  </xsl:function>
</xsl:stylesheet>

Остерегайтесь бесконечных циклов, если компонент1 ссылается на компонент2, а компонент2 ссылается на компонент1

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