简体   繁体   中英

XSLT Copy Child nodes and turn them into Parents

I have the following input:

<Article>
<title>Apple</title>
<number>119.057</number>
<price>90.8</price>
  <option>
    <Article>
        <title>Apple Green</title>
        <price>144.2</price>
        <number>119.086</number>
    </Article>
  </option>
</Article>
<Article>
      <title>Coconut</title>
      <number>120.882</number>
      <price>10.00</price>
</Article>
<Article>
      <title>Pinapple</title>
      <number>120.883</number>
      <price>19.00</price>
 </Article>

and it should look like this:

 <Article>
   <title>Apple</title>
   <number>119.057</number>
   <price>90.8</price>
 </Article>
 <Article>
   <title>Apple Green</title>
   <price>144.2</price>
   <number>119.086</number>
 </Article>
 <Article>
   <title>Coconut</title>
   <number>120.882</number>
   <price>10.00</price>
 </Article>
 <Article>
   <title>Pinapple</title>
   <number>120.883</number>
   <price>19.00</price>
 </Article>

My Attempt so far:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" />
<xsl:template match="root/Article">
    <xsl:apply-templates/>
</xsl:template>

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

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

In fact i need to remove The option-Tag and the Child-Tags should become Article-Tags. So that all nodes are on the same Level in the Tree and finally remove the option Tag.

Thanks for your Inputs!

You wrote: "i need to remove the options tag and their child tags should become (direct chilren of) Article tag".

Then do just that, but with a minor correction: the tag you want to match (and remove in the output) is option (not options ).

<xsl:template match="Article/option">
  <xsl:apply-templates />
</xsl:template>

Note the similarity to the identity template. The main difference is that there is no xsl:copy tag (which would have copied the original option tag).

Edit

Initially I presented only the template. Below you have the full script:

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

  <xsl:template match="Article/option">
    <xsl:apply-templates />
  </xsl:template>

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

It does generate the required output.

Edit 2

Yet another solution. It copies only option content, but to keep the proper XML formatting, I added an "envelope" root ( main ) tag.

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

  <xsl:template match="/Article">
    <!-- This matches only the root Article tag, not its grandson -->
    <main>  <!-- You need to have a main (root) tag -->
      <!-- Output only the option content -->
      <xsl:apply-templates select="option"/>
    </main>
  </xsl:template>

  <xsl:template match="option">
    <xsl:apply-templates/>
  </xsl:template>

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

Given a well-formed input such as:

XML

<Articles>
  <Article>
    <title>Apple</title>
    <number>119.057</number>
    <price>90.8</price>
    <option>
      <Article>
        <title>Apple Green</title>
        <price>144.2</price>
        <number>119.086</number>
      </Article>
    </option>
  </Article>
  <Article>
    <title>Coconut</title>
    <number>120.882</number>
    <price>10.00</price>
  </Article>
  <Article>
    <title>Pinapple</title>
    <number>120.883</number>
    <price>19.00</price>
  </Article>
</Articles>

the following stylesheet:

XSLT 1.0

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

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

<xsl:template match="Article">
    <xsl:copy>
        <xsl:apply-templates select="*[not(self::option)]"/>
    </xsl:copy>
    <xsl:apply-templates select="option"/>
</xsl:template>

<xsl:template match="option">
    <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

will transform an option node from being a child of Article to being its sibling, returning:

Result

<?xml version="1.0" encoding="UTF-8"?>
<Articles>
  <Article>
    <title>Apple</title>
    <number>119.057</number>
    <price>90.8</price>
  </Article>
  <Article>
    <title>Apple Green</title>
    <price>144.2</price>
    <number>119.086</number>
  </Article>
  <Article>
    <title>Coconut</title>
    <number>120.882</number>
    <price>10.00</price>
  </Article>
  <Article>
    <title>Pinapple</title>
    <number>120.883</number>
    <price>19.00</price>
  </Article>
</Articles>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM