tags:

views:

848

answers:

4

I have an XML file from which I need to delete an attribute with name "Id" (It must be deleted wherever it appears) and also I need to rename the parent tag, while keeping its attributes and child elements unaltered .. Can you please help me modifying the code. At a time, am able to achieve only one of the two requirements .. I mean I can delete that attribute completely from the document or I can change the parent tag .. Here is my code to which removes attribute "Id":

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

Please help me changing the parent tag name from "Root" to "Batch".

+2  A: 

I would try:

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

The first block copies all that is not specified, as you use. The second replaces @id with nothing wherever is occurs. The third renames /Root to /Batch.

rsp
thank you very much. :-)
infant programmer
+2  A: 
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()|text()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="@Id" />
<xsl:template match="Root">
  <Batch>
    <xsl:copy-of select="@*|*|text()" />
  </Batch>
</xsl:template>
Erlock
Root[@Id] becomes Batch[@Id] instead of being filtered out. The Root rule should apply-templates.
Paul Butcher
instead of <xsl:copy-of select="@*|*"/>I wrote <xsl:apply-templates select="@*|*"> it worked ..can you explain me why xslt behaves like this ?
infant programmer
copy-of will create copies of everything selected without regard to existing templates. apply-templates applies the templates. There is a template for @Id that has a null output.
Paul Butcher
thank you very much paul :)
infant programmer
Maybe I misinterpreted 'I need to rename the parent tag, while keeping its attributes and child elements unaltered'?
Erlock
+2  A: 

This should do the job:

<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()|text()" />
      </xsl:copy>
   </xsl:template>

   <xsl:template match="node()[node()/@Id]">
      <batch>
         <xsl:apply-templates select='@*|*|text()' />
      </batch>
   </xsl:template>

   <xsl:template match="@Id">
   </xsl:template>
</xsl:stylesheet>

I tested with the following XML input:

<root anotherAttribute="1">
<a Id="1"/>
<a Id="2"/>
<a Id="3" anotherAttribute="1">
    <b Id="4"/>
    <b Id="5"/>
</a>

wwerner
As I understood the question, not only the tag named root should be renamed, but all parent tags that contain an element with an Id attribute. If this is correct, simply matching "Root" would not do the job.If not, it is sufficient to match "Root"
wwerner
Thank you very much. :)
infant programmer
+1  A: 

None of the offered solutions really solves the problem: they simply rename an element named "Root" (or even just the top element), without verifying that this element has an "Id" attribute.

wwerner is closest to a correct solution, but renames the parent of the parent.

Here is a solution that has the following properties:

  • It is correct.
  • It is short.
  • It is generalized (the replacement name is contained in a variable).

Here is the code:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:variable name="vRep" select="'Batch'"/>

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

  <xsl:template match="@Id"/>

  <xsl:template match="*[@Id]">
    <xsl:element name="{$vRep}">
      <xsl:apply-templates select="node()|@*"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
Dimitre Novatchev
oh! you are correct! well I never observed this, in-fact in my practical XML root never had "id" attribute, so it has gone unobserved all the time .. I am really thankful to you :-) And nothing can deny accepting this answer .. :-)
infant programmer