Сгруппировать похожие узлы в XML с помощью XSLT

У меня есть следующая структура XML

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <BookingGroup>
        <PostCodes>
            <PostCode >AB</PostCode>
            <PostCode >AL</PostCode>
        </PostCodes>
    </BookingGroup>
    <BookingGroup>
        <PostCodes>
            <PostCode >AB</PostCode>
            <PostCode >D</PostCode>
        </PostCodes>
    </BookingGroup>
</Root>

Теперь для каждого почтового индекса AB во всем Xml мне нужен вывод как:

<Root>
    <Child>
        <Child1>
        </Child1>
        <Child1>
        </Child1>
</root>

поскольку есть два почтовых индекса AB, мне нужно два элемента child1.


person Community    schedule 21.07.2009    source источник
comment
Вопрос в его нынешней формулировке непонятен.   -  person jrockway    schedule 21.07.2009
comment
Интересно, люди когда-нибудь читали то, что пишут? Никто не может на самом деле быть настолько ограниченным, и одновременно работать с XML. Но опять же, возможно, это возможно. xkcd.com/481   -  person Tomalak    schedule 21.07.2009


Ответы (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" indent="yes"/>

  <xsl:variable name="firstNode" select="//PostCode[1]"/>
  <!-- for a literal value use <xsl:variable name="firstNode">AB</xsl:variable> -->

  <xsl:template match="Root">
    <Root>
      <Child>
    <xsl:apply-templates select="//PostCode"/>
      </Child>
    </Root>
  </xsl:template>

  <xsl:template match="PostCode">
    <xsl:if test=".=$firstNode">
      <Child1>
    <xsl:apply-templates select="@* | node()"/>
      </Child1>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Если вы ищете общее решение, которое будет выводить любые узлы на входе, попробуйте это

<?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" indent="yes"/>

  <xsl:variable name="firstNode" select="//PostCode[1]"/>
  <!-- for a literal value use <xsl:variable name="firstNode">AB</xsl:variable> -->

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

  <xsl:template match="PostCode">
    <xsl:if test=".=$firstNode">
      <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
person cordsen    schedule 29.05.2011