1
votes

I have xml file like follows,

<doc>
  <a ref="Foot"></a>
  <a ref="Foot"></a>
  <a ref="Foot"></a>
  <a ref="End"></a>
  <a ref="End"></a>
  <a ref="End"></a>
<doc>

my requirement was add dynamically increment id attribute to the <a> node that have "End" attribute. and also change "Foot" attribute with "End" so the result document would be,

<doc>
  <a ref="End" id="1"></a>
  <a ref="End" id="2"></a>
  <a ref="End" id="3"></a>
  <a ref="End" id="4"></a>
  <a ref="End" id="5"></a>
  <a ref="End" id="6"></a>
<doc>

I was able to add dynamic id to nodes and change the "Foot" attribute with "End" but the id's only added to the node which previously have "End" attribute. nodes which have attribute "Foot" do not add the id. My current output is follows,

<doc>
  <a ref="End"></a>
  <a ref="End"></a>
  <a ref="End"></a>
  <a ref="End" id="1"></a>
  <a ref="End" id="2"></a>
  <a ref="End" id="3"></a>
<doc>

My xsl code is follows,

//adds dynamic id's to foot node

<xsl:template match="a/@ref[.='End']">
   <xsl:attribute name="id">
        <xsl:number count="a[@ref='End']" level="any"></xsl:number>
   </xsl:attribute>
</xsl:template>


//change attribute "Foot" to attribute "End" 

 <xsl:template match="a/@ref[. = 'Foot']">
        <xsl:attribute name="id">End</xsl:attribute>
 </xsl:template>

My problem is how can add id's to first three nodes. I may could use xsl variables but I'm new to xslt and i couldn't thik of a way how can I use variables. also if we can do the "Foot" attribute to "End" attribute conversation first and then add the id's then code will run fine. I also have no idea of is it possible with xslt.

can anyone suggest me an answer how can I do this?

Thanks in advance.

2
Is that the real code you have? Given <a ref="Foot"></a> I don't get why you write match="a[. = 'Foot']" and not <xsl:template match="a/@ref[. = 'Foot']"><xsl:attribute name="ref">End</xsl:attribute>?Martin Honnen
Will there be a elements whose ref attribute is neither "Foot" nor "End"? If yes, how should they be handled?michael.hor257k
@MartinHonnen , yes, this is not the real code. just a sample code. sorry for the mistake . I'he edited it nowsanjay
@michael.hor257k , there are no other a elements which have different attributessanjay

2 Answers

2
votes

Here is how you can do it:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

  <xsl:output omit-xml-declaration="yes"/>

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

  <!-- Add sequential id attribute; set ref attribute value to "End" -->
  <xsl:template match="a">
    <a ref="End">
      <xsl:attribute name="id"><xsl:number/></xsl:attribute>
    </a>
  </xsl:template>

</xsl:stylesheet>

Output from Saxon:

<doc>
  <a ref="End" id="1"/>
  <a ref="End" id="2"/>
  <a ref="End" id="3"/>
  <a ref="End" id="4"/>
  <a ref="End" id="5"/>
  <a ref="End" id="6"/>
</doc>
2
votes

If you want to number all a elements sequentially, no matter what the @ref attribute contains, why don't you simply do:

<xsl:template match="a">
    <a id="{position()}">
        <xsl:apply-templates select="@*|node()"/>
    </a>
</xsl:template>

Or, if you also want to convert all of them to ref="End" (and assuming they have no content), even simpler:

<xsl:template match="a">
    <a ref="End" id="{position()}"/>
</xsl:template>