Как объединить узлы XML с общим значением атрибута - PullRequest
0 голосов
/ 18 сентября 2018

Я хотел бы взять некоторый документ XML и объединить все узлы на некотором уровне, которые имеют одинаковое значение атрибута.Например, если у меня есть документ такой формы,

<xml>
 <books id="X">
  <book name="Story"/>
  <book name="Tale"/>
 </books>
 <books id="X">
  <book name="Folklore"/>
  <book name="Magic"/>
 </books>
 <books id="Y">
  <book name="Harry Potter"/>
  <book name="LotR"/>
 </books>
</xml>

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

<xml>
 <books id="X">
  <book name="Story"/>
  <book name="Tale"/>
  <book name="Folklore"/>
  <book name="Magic"/>
 </books>
 <books id="Y">
  <book name="Harry Potter"/>
  <book name="LotR"/>
 </books>
</xml>

Если это вообще возможно,Мне бы очень хотелось несколько решений.Например, один с XSLT и другой с другим языком.

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Вы можете попробовать это:

<xsl:template match="xml">
        <xsl:for-each-group select="books" group-by="@id">
            <xsl:copy>
                <xsl:attribute name="id" select="current-grouping-key()"/>
                <xsl:apply-templates select="current-group()/*"/>
            </xsl:copy>
        </xsl:for-each-group>
    </xsl:template>

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

См. Преобразование в https://xsltfiddle.liberty -development.net / gWmuiJR

0 голосов
/ 18 сентября 2018
<xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="books[1][@id='X']">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
        <xsl:apply-templates/>
            <xsl:apply-templates select="following-sibling::books[@id='X']/book"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="books[@id='X' and preceding-sibling::books[@id='X']]"/>
    <xsl:template match="book">
        <xsl:copy>
        <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
check it.
...