как найти элемент в исходном XML-файле динамически в цикле - PullRequest
0 голосов
/ 02 июля 2018

, если у нас есть следующий ввод XML:

<root xmlns:ns="http://www.blabla">
  <ns:element1 attribute="attr1">10</ns:element1>
  <ns:element1 attribute="attr2">20</ns:element1>

  <ns:element2 attribute="attr1">30</ns:element1>
  <ns:element2 attribute="attr2">40</ns:element1>
</root>

как мы можем найти каждый элемент внутри for-each в xslt?

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="root">
        <html>
            <body>
                <h2>My Collection</h2>
                <table border="1">
                    <tr bgcolor="#9acd32">
                        <th style="text-align:left">Column 1</th>
                        <th style="text-align:left">Column 2</th>
                    </tr>
                    <xsl:for-each select="1 to 10">
                        <xsl:variable name="name" select="concat('element', .)"/>
                        <tr>
                        <td>
                            <xsl:value-of select="???what should be here???[lower-case(@attribute)='attr0']"/>
                        </td>
                        <td>
                            <xsl:value-of select="???same question???[lower-case(@attribute)='attr1']"/>
                        </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>

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

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Если у вас нет контроля, попробуйте подсчитать количество элементов и запустить цикл в соответствии с таким количеством:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:ns="http://www.blabla">
    <xsl:template match="root">
        <html>
            <body>
                <h2>My Collection</h2>
                <table border="1">
                    <tr bgcolor="#9acd32">
                        <th style="text-align:left">Column 1</th>
                        <th style="text-align:left">Column 2</th>
                    </tr>
                    <xsl:variable name="all-element" select="count(//*:element)"/>
                    <xsl:for-each select="*[concat('ns:element', (1 to $all-element))]">
                        <xsl:message select="."/>
                        <tr>
                            <td>
                                <xsl:value-of select="@attribute"/>
                            </td>
                            <td>
                                <xsl:value-of select="."/>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>
0 голосов
/ 02 июля 2018

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

<xsl:value-of select="*[local-name() = $name][lower-case(@attribute)='attr1']"/>

... За исключением этого произойдет сбой с ошибкой вдоль строк Required item type of context item for the child axis is node(); supplied expression (.) has item type xs:integer, из-за кода, выполняемого в контексте xsl:for-each для атомарных значений. Чтобы обойти это, вам нужно сохранить ссылку на дочерние элементы в переменной до xsl:for-each.

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

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="root">
        <html>
            <body>
                <h2>My Collection</h2>
                <table border="1">
                    <tr bgcolor="#9acd32">
                        <th style="text-align:left">Title</th>
                    </tr>
                    <xsl:variable name="children" select="*" />
                    <xsl:for-each select="1 to 10">
                        <xsl:variable name="name" select="concat('element', .)"/>
                        <tr>
                        <td>
                            <xsl:value-of select="$children[local-name() = $name][lower-case(@attribute)='attr1']"/>
                        </td>
                        <td>
                            <xsl:value-of select="$children[local-name() = $name][lower-case(@attribute)='attr2']"/>
                        </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Или немного лучше, чтобы уменьшить дублирование кода ...

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="root">
        <html>
            <body>
                <h2>My Collection</h2>
                <table border="1">
                    <tr bgcolor="#9acd32">
                        <th style="text-align:left">Title</th>
                    </tr>
                    <xsl:variable name="children" select="*" />
                    <xsl:for-each select="1 to 10">
                        <xsl:variable name="name" select="concat('element', .)"/>
                        <xsl:variable name="element" select="$children[local-name() = $name]"/>
                        <tr>
                        <td>
                            <xsl:value-of select="$element[lower-case(@attribute)='attr1']"/>
                        </td>
                        <td>
                            <xsl:value-of select="$element[lower-case(@attribute)='attr2']"/>
                        </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

Обратите внимание, я бы действительно подумал об изменении вашего входного XML, если у вас есть контроль над ним. Нумерация элементов с использованием имени элемента затрудняет манипулирование. В идеале вы бы сделали это вместо ...

<ns:element num="1" attribute="attr1">10</ns:element>
...