XSLT for-each цикл, повторяющийся через 2 элемента с одинаковым именем, но с другим атрибутом - PullRequest
0 голосов
/ 04 июля 2018

Примечание: решение должно быть в XSLt 1.0

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

У меня есть XML-файл с несколькими узлами, например:

<Roles>
  <field name="linecode" instance="1" value="EY"/>
  <field name="number" instance="1" value="265"/>
  <field name="linecode" instance="2" value="PK"/>
  <field name="number" instance="2" value="123"/>
  <field name="abc" instance="1" value="123"/>
  <field name="xyz" instance="1" value="123"/>
</Role>

Мне нужно перебрать эти узлы и вывести <field name="linecode"> вместе с соответствующим ему экземпляром № <field name="number">. Однако, если я использую цикл for-each, он будет перебирать штраф <field name="linecode">s, но вывести тот же <field name="number"> не работает.

Можно ли как-нибудь синхронизировать их, чтобы, например, вывод был

EY - 265
PK - 123

Я также пытался использовать following-sibling, но он не работает для меня. Любая помощь высоко ценится. .

Вот мой пример xslt.

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

<xsl:template match="Roles">
    <xsl:for-each select="field[@name='linecode']">
        <xsl:value-of select="@value"/>
        <xsl:text> - </xsl:text>
        <xsl:value-of select="field[@name='number' and instance='@instance']"/>
        <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
</xsl:template>

Если бы кто-нибудь мог придумать альтернативу циклам, которая бы тоже работала, я был бы признателен.

Ответы [ 3 ]

0 голосов
/ 04 июля 2018
<xsl:template match="Roles">
        <xsl:for-each select="field">
            <xsl:if test="@name='linecode'">
            <xsl:value-of select="@value"/>
                <xsl:text> - </xsl:text>
            </xsl:if>

            <xsl:if test="@name='number'">
                <xsl:value-of select="@value"/>
                <xsl:text>&#xa;</xsl:text>
            </xsl:if>

        </xsl:for-each>
Also try it
0 голосов
/ 04 июля 2018

Если под «совпадающим экземпляром» вы подразумеваете непосредственно следующий элемент поля, тогда вы можете использовать

<xsl:value-of select="following-sibling::field[1]/@value"/>

Но если «совпадающий экземпляр» означает числовое поле с тем же идентификатором, тогда используйте

<xsl:value-of select="../field[@name='number' and @instance=current()/@instance]/@value"/>
0 голосов
/ 04 июля 2018

Вы хотите получить следующее выражение:

<xsl:value-of select="../field[@name='number' and @instance=current()/@instance]/@value"/>

Обратите внимание на использование ../ в начале. Если вы только что сделали <xsl:value-of select="field.." />, вы бы попытались выбрать дочерний элемент с именем field, когда вы уже позиционированы на элементе field. Выполнение .. сначала выбирает родительский узел, что позволяет вам выбрать элемент одного уровня.

Также обратите внимание на использование current(), которое относится к узлу, на котором вы сейчас находитесь (тот, который вы выбрали с помощью xsl:for-each). Читайте о "текущий узел против узла контекста" здесь: Текущий узел против узла контекста в XSLT / XPath?

Кроме того, вы можете узнать об использовании ключей здесь. Вы можете определить ключ для поиска элементов field по их атрибуту instance

<xsl:key name="fields" match="field" use="@instance" />

Итак, чтобы посмотреть элемент, вы делаете это ..

<xsl:value-of select="key('fields', @instance)[@name = 'number']/@value"/>

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

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

<xsl:key name="fields" match="field" use="@instance" />

<xsl:template match="Roles">
    <xsl:for-each select="field[@name='linecode']">
        <xsl:value-of select="@value"/>
        <xsl:text> - </xsl:text>
        <xsl:value-of select="key('fields', @instance)[@name = 'number']/@value"/>
        <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>
...