xml - XSLT - Add new attributes and node -


i have xml follows,

<doc>     <a type="atr111"></a>     <a type="atr111"></a>     <a type="atr111"></a>     <a type="atr222"></a>     <a type="atr222"></a>     <a type="atr222"></a> </doc> 

my requirements are,

  1. add dynamically increment id attribute nodes has attribute atr111 , atr222
  2. add new node inside nodes, named <newnode> having attribute id="newattr" has attribute atr111 , atr222
  3. change <a> nodes attribute value atr111 atr222.

so expected output is,

<doc>     <a id="id-1" type="atr222"><newnode id="newattr"/></a>     <a id="id-2" type="atr222"><newnode id="newattr"/></a>     <a id="id-3" type="atr222"><newnode id="newattr"/></a>     <a id="id-4" type="atr222"><newnode id="newattr"/></a>     <a id="id-5" type="atr222"><newnode id="newattr"/></a>     <a id="id-6" type="atr222"><newnode id="newattr"/></a> </doc> 

the xsl have written output follows,

<xsl:template match="a" priority="1">         <!-- add new dynamic id -->       <xsl:copy>             <xsl:attribute name="id">                 <xsl:value-of select="'id-'"/>                  <xsl:number count="a[@type='atr111' or @type='atr222']" level="any"/>             </xsl:attribute>         </xsl:copy>          <!-- add newnode inside <a> node -->         <xsl:copy>         <newnode>             <xsl:attribute name="id">newattr</xsl:attribute>         </newnode>       </xsl:copy>     </xsl:template>      <!-- change existing 'atr111' attribute value 'atr222' -->     <xsl:template match="a/@type[. = 'atr111']">         <xsl:attribute name="type">atr222</xsl:attribute>     </xsl:template>   

my current output comes follows,

<doc>     <a id="id-1"/><a><newnode id="newattr"/></a>     <a id="id-2"/><a><newnode id="newattr"/></a>     <a id="id-3"/><a><newnode id="newattr"/></a>     <a id="id-4"/><a><newnode id="newattr"/></a>     <a id="id-5"/><a><newnode id="newattr"/></a>     <a id="id-6"/><a><newnode id="newattr"/></a> </doc> 

as can see dynamic ids have added expected, , <newnode> new attribute has added.but has duplicated <a> node. existing attribute type has disappeared.

how can organize code expected output?

you forgot copy type attribute. <xsl:copy> copies current node itself, not children or attributes.

the following utilizes identity template process of copying children , attributes.

<xsl:transform xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0">     <xsl:output encoding="utf-8" indent="yes" />      <xsl:template match="@*|node()">         <xsl:copy>             <xsl:apply-templates select="@*|node()"/>         </xsl:copy>     </xsl:template>      <xsl:template match="a[@type='atr111' or @type='atr222']">         <xsl:copy>             <xsl:attribute name="id">                 <xsl:text>id-</xsl:text>                 <xsl:number count="a[@type='atr111' or @type='atr222']" level="any" />             </xsl:attribute>             <xsl:apply-templates select="@*|node()" />             <newnode id="newattr" />         </xsl:copy>     </xsl:template> </xsl:transform> 

output:

<doc>     <a id="id-1" type="atr111"><newnode id="newattr"/></a>     <a id="id-2" type="atr111"><newnode id="newattr"/></a>     <a id="id-3" type="atr111"><newnode id="newattr"/></a>     <a id="id-4" type="atr222"><newnode id="newattr"/></a>     <a id="id-5" type="atr222"><newnode id="newattr"/></a>     <a id="id-6" type="atr222"><newnode id="newattr"/></a> </doc> 

you of course use <xsl:copy-of select="@type" /> if there no other children, that's less flexible: copying through identity template enables carry on variable input , add, example, <xsl:template match="a/@type"> later-on special processing @type nodes, if necessary.


Comments