2012-08-08 1 views
1


Я преобразуя этот XML:
Как я могу объединить все эти теги XML в один более крупный тег с тем же именем с помощью XSLT?

<root> 
    <contrib contrib-type="author"> 
    <name> 
     <last-name>Kottke</last-name> 
     <first-name>Leo</first-name> 
    </name> 
    </contrib> 

    <contrib contrib-type="author"> 
    <name> 
     <last-name>McKee</last-name> 
     <first-name>Andy</first-name> 
    </name> 
    </contrib> 

    <contrib contrib-type="author"> 
    <name> 
     <last-name>Hedges</last-name> 
     <first-name>Michael</first-name> 
    </name> 
    </contrib> 
</root> 

... с этим XSL:

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

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

     <!-- Authors --> 
     <xsl:template match="contrib[@contrib-type='author']"> 
      <Authors> 
       <xsl:if test="position() != last()"> 
       <xsl:value-of select = "concat(name/first-name, ' ', name/last-name, ', ')" /> 
       </xsl:if> 

       <xsl:if test="position() = last()"> 
       <xsl:value-of select = "concat('and ', name/first-name, ' ', name/last-name, '.')" /> 
       </xsl:if> 
      </Authors> 
     </xsl:template> 
</xsl:stylesheet> 

... и я получаю этот выход:

<root> 
    <Authors>Leo Kottke, </Authors> 
    <Authors>Andy McKee, </Authors> 
    <Authors>and Michael Hedges.</Authors> 
</root> 





Однако, я пытаюсь объединить все   Author   тегов в одну большую   Author   тега, так что результат будет выглядеть примерно:

<root> 
    <Authors>Leo Kottke, Andy McKee, and Michael Hedges.</Authors> 
</root> 


Do Мне нужно каким-то образом использовать цикл  ?

ответ

2

No xsl:for-each Необходимо. Просто добавьте шаблон для /* (или /root) и удалить Authors из вашего contrib матча:

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

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

    <xsl:template match="/root"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <Authors> 
       <xsl:apply-templates select="contrib[@contrib-type='author']"/> 
      </Authors> 
     </xsl:copy> 
    </xsl:template> 

    <!-- Authors --> 
    <xsl:template match="contrib[@contrib-type='author']"> 
     <xsl:if test="position() != last()"> 
      <xsl:value-of select = "concat(name/first-name, ' ', name/last-name, ', ')" /> 
     </xsl:if> 

     <xsl:if test="position() = last()"> 
      <xsl:value-of select = "concat('and ', name/first-name, ' ', name/last-name, '.')" /> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Спасибо @DevNull за помощь! Тем не менее, у меня есть много других таких тегов для преобразования, помимо «Авторов», и добавление этого кода в остальную часть противоречит и вызывает * только * 'Authors' для вывода ... –

+0

А, поэтому я изменил' 'to' ', и теперь он работает нормально. Я не совсем уверен, что я понял, но похоже, что применение преобразования авторов ко всем атрибутам сводило к нулю все узлы, которые не соответствовали условию. Еще раз спасибо @DevNull! –

+0

Хороший ответ, +1. – ABach

2

что-то немного проще

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/root"> 
     <xsl:variable name="authors"> 
      <xsl:for-each select="contrib/name"> 
       <xsl:text>, </xsl:text> 
       <xsl:value-of select="first-name"/> 
       <xsl:text> </xsl:text> 
       <xsl:value-of select="last-name"/> 
      </xsl:for-each> 
     </xsl:variable> 

     <root> 
      <authors><xsl:value-of select="substring($authors,3)"/></authors> 
     </root> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Спасибо @ Jim за помощь! Тем не менее, количество имен неизвестного размера (не всегда просто 3), а позиция элемента '' будет меняться по отношению к корню ... –

+1

В моем нет ничего ответ, который ограничивает все до 3 случаев. Что касается различной глубины, просто измените выбор на '.// contrib/name'. –

+0

Ах, извините, я неправильно понял строку '', и еще раз спасибо за информацию ... так что указывает это утверждение? Я получил ожидаемые результаты при тестировании на http://xsltcake.com/, однако без окончательного «и» и периода. –