2009-11-28 2 views
2

У меня есть следующий XML:XSLT: выбрать различные, но немного отличается от других примеров

<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="https://stackoverflow.com/a/b/*"> 
    <xsl:sort select="name(.)"/> 
    <xsl:value-of select="name(.)" /> 
</xsl:for-each> 

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

ответ

1

Сначала добавьте этот ключевой элемент в верхней части XSL: -

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

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

<xsl:template match="/*"> 
    <xsl:for-each select="https://stackoverflow.com/a/b/*[count(. | key('tagNames', name())[1]) = 1]"> 
     <xsl:sort select="name()" /> 
     <xsl:value-of select="name()" /> 
    </xsl:for-each> 
</xsl:template> 
+0

Спасибо - работает хорошо. – sellotape

0

Вы можете использовать Muenchian метод:

<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> 
+0

Спасибо. Мой пример был явно упрощен - будет ли это работать так же хорошо (с совпадениями * там), когда мой XML является небольшой частью более крупного документа? – sellotape

+0

Это, вероятно, работает в опубликованном упрощенном случае, но есть сценарии, в которых это не будет выполнено из-за того, что ключевой элемент, соответствующий __all__-элементам документа, а не только дочерние элементы/a/b. – AnthonyWJones

+0

Согласовано. Цель состояла в том, чтобы показать концепцию (и заставить ее работать на примере). Код должен быть изменен, чтобы соответствовать сценарию реальной жизни (т. Е. Использовать/a/b * в качестве ключа). Я просто неполный, чтобы по возможности использовать шаблоны против каждой конструкции. – Goran