XSLT: совпадение элементов, начиная со 2-го появления - PullRequest
0 голосов
/ 11 октября 2019

надеюсь, ты сможешь мне помочь. Я ищу общий шаблон соответствия XSLT, который сопоставляет все элементы определенного имени после первого появления. В этом примере все должно быть скопировано с помощью преобразования идентичности, первое вхождение «line» необходимо «сделать что-то логическое, а все элементы« line »после первого должны игнорироваться». Элементы "линии" в теории могут происходить бесконечно много раз.

Пример исходного XML:

<?xml version="1.0" encoding="UTF-8"?>
<sampledoc>
    <header1>a1</header1>
    <header2>b1</header2>
    <header3>c1</header3>
    <line>a2</line>
    <line>b2</line>
    <line>c2</line>
    <line>c3</line>
    <line>c4</line>
    <footer>bye</footer>
</sampledoc>

Я бы ожидал что-то вроде following::line[1], но не заставил бы его работать. Так что это моя "статическая" версия:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="line[1]">
        <!-- Do something --> 
    </xsl:template>

    <xsl:template match="line[2]"/>
    <xsl:template match="line[3]"/>
    <xsl:template match="line[4]"/>
    <xsl:template match="line[5]"/>
    <xsl:template match="line[6]"/>
    <xsl:template match="line[7]"/>



</xsl:stylesheet>

Спасибо!

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Вам необходимо узнать о приоритетах соответствия шаблонов. В частности, шаблон, сопоставляющий элемент с условием, имеет более высокий приоритет, чем просто сопоставление имени элемента самостоятельно. (В частности, сопоставление с шаблоном line[1] имеет приоритет 0,5, а сопоставление с шаблоном line имеет приоритет 0.)

Это означает, что вам нужны только следующие шаблоны.

<xsl:template match="line[1]">
    <newline /> 
</xsl:template>

<xsl:template match="line"/>

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

См. https://www.w3.org/TR/xslt-10/#conflict для получения более подробной информации.

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

     <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="line[1]">
        <newline /> 
    </xsl:template>

    <xsl:template match="line"/>
</xsl:stylesheet>

(Обратите внимание, что ваш шаблон, соответствующий /, в этом случае не требуется, так как XSLT built-в шаблонах будет делать то же самое)

0 голосов
/ 11 октября 2019

Используйте <xsl:template match="line[position() > 1]"/>, чтобы не обрабатывать дочерний элемент второй, третьей, четвертой строки.

...