XSLT: выберите разные, но немного отличающиеся от других примеров - PullRequest
2 голосов
/ 28 ноября 2009

У меня есть следующий XML:

<a>
    <b>
        <d>D1 content (can include child nodes)</d>
    </b>
    <b>
        <c>C1 content (can include child nodes)</c>
    </b>
    <b>
        <e>E1 content (can include child nodes)</e>
    </b>
    <b>
        <c>C2 content (can include child nodes)</c>
    </b>
</a>

Используя XSLT 1.0, мне нужно произвести из этого просто: "cde"; то есть отдельный список имен ближайших потомков / a / b /, упорядоченных по имени узла. У каждого b ровно один дочерний элемент произвольного имени.

Я могу произвести "ccde":

<xsl:for-each select="/a/b/*">
    <xsl:sort select="name(.)"/>
    <xsl:value-of select="name(.)" />
</xsl:for-each>

Я пытался использовать обычное сравнение previous-sibling ::, но так как у каждого b есть только один дочерний элемент, предыдущий брат всегда ничего.

Ответы [ 2 ]

1 голос
/ 28 ноября 2009

Сначала добавьте этот ключевой элемент в начало вашего XSL: -

<xsl:key name="tagNames" match="/a/b/*" use="name()" /> 

Теперь ваш цикл для каждого цикла может выглядеть следующим образом: -

<xsl:template match="/*">
    <xsl:for-each select="/a/b/*[count(. | key('tagNames', name())[1]) = 1]">
        <xsl:sort select="name()" />
        <xsl:value-of select="name()" />
    </xsl:for-each>
</xsl:template>
0 голосов
/ 28 ноября 2009

Вы можете использовать метод Мюнхена:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="groupIndex" match="*" use="name()" />
    <xsl:template match="/">
        <xsl:apply-templates select="a/b"/>
    </xsl:template>
    <xsl:template match="b">
        <xsl:apply-templates select="*[1][generate-id(.) = generate-id(key('groupIndex', name())[1])]" mode="group" />
    </xsl:template>
    <xsl:template match="*" mode="group">
        <xsl:value-of select="name()"/>
    </xsl:template>
</xsl:stylesheet>
...