xslt - Unnest parent nodes by child node -


in xml there items 0-n attributes , item should copied each attribute new item 1 attribute.

given xml this:

<?xml version="1.0" encoding="utf-8" ?> <items>     <item>         <name>a</name>         <attributes>             <attribute>                 <key>attribute1</key>                 <value>1</value>             </attribute>         </attributes>     </item>     <item>         <name>b</name>     </item>     <item>         <name>c</name>         <attributes>             <attribute>                 <key>attribute1</key>                 <value>5</value>             </attribute>             <attribute>                 <key>attribute2</key>                 <value>2</value>             </attribute>             <attribute>                 <key>attribute3</key>                 <value>1</value>             </attribute>         </attributes>     </item> </items> 

result should be:

<?xml version="1.0" encoding="utf-8" ?> <root>     <item>         <name>a</name>         <attribute_key>attribute1</attribute_key>         <attribute_value>1</attribute_value>     </item>     <item>         <name>b</name>     </item>     <item>         <name>c</name>         <attribute_key>attribute1</attribute_key>         <attribute_value>5</attribute_value>     </item>     <item>         <name>c</name>         <attribute_key>attribute2</attribute_key>         <attribute_value>2</attribute_value>     </item>     <item>         <name>c</name>         <attribute_key>attribute3</attribute_key>         <attribute_value>1</attribute_value>     </item> </root> 

what have s far:

<?xml version="1.0" encoding="utf-8" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0">  <xsl:template match="@* | node()">   <xsl:copy>     <xsl:apply-templates select="@* | node()"/>   </xsl:copy> </xsl:template>  <xsl:template match="item">     <xsl:if test="not(attributes/attribute)">         <item>             <xsl:apply-templates select="@* | node()"/>         </item>     </xsl:if>     <xsl:for-each select="./attributes/attribute">         <xsl:copy-of  select="ancestor::item"/>     </xsl:for-each>  </xsl:template>  </xsl:stylesheet> 

so, parent "item" node gets copied correctly how remove attributes attribute for-each , place attribute direct child of "item"?

instead of copying item node in entirity, manually create new item , copy children (apart attributes)

<xsl:for-each select="attributes/attribute">     <item>         <xsl:copy-of select="ancestor::item/*[not(self::attributes)]"/>         <!-- process attributes here -->     </item> </xsl:for-each> 

processing attributes matter of processing children, , using xsl:element create new ones

    <xsl:for-each select="*">         <xsl:element name="attribute_{local-name()}">             <xsl:value-of select="." />         </xsl:element>     </xsl:for-each> 

try xslt

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:output method="xml" indent="yes" />  <xsl:template match="@* | node()">   <xsl:copy>     <xsl:apply-templates select="@* | node()"/>   </xsl:copy> </xsl:template>  <xsl:template match="item">     <xsl:if test="not(attributes/attribute)">         <item>             <xsl:apply-templates select="@* | node()"/>         </item>     </xsl:if>      <xsl:for-each select="attributes/attribute">         <item>             <xsl:copy-of select="ancestor::item/*[not(self::attributes)]"/>             <xsl:for-each select="*">                 <xsl:element name="attribute_{local-name()}">                     <xsl:value-of select="." />                 </xsl:element>             </xsl:for-each>         </item>     </xsl:for-each>  </xsl:template> </xsl:stylesheet> 

or if wanted take more template-based approach, should work

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:output method="xml" indent="yes" />  <xsl:template match="@* | node()">   <xsl:copy>     <xsl:apply-templates select="@* | node()"/>   </xsl:copy> </xsl:template>  <xsl:template match="item[attributes/attribute]">     <xsl:apply-templates select="attributes/attribute" /> </xsl:template>  <xsl:template match="item">     <item>         <xsl:apply-templates select="@* | node()"/>     </item> </xsl:template>  <xsl:template match="attribute">     <item>         <xsl:copy-of select="ancestor::item/*[not(self::attributes)]"/>         <xsl:apply-templates select="*" />     </item> </xsl:template>  <xsl:template match="attribute/*">     <xsl:element name="attribute_{local-name()}">         <xsl:value-of select="." />     </xsl:element> </xsl:template> </xsl:stylesheet> 

Comments

Popular posts from this blog

c - Bitwise operation with (signed) enum value -

YouTubePlayerFragment cannot be cast to android.support.v4.app.Fragment -