Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 24th, 2013, 01:42 AM
Registered User
 
Join Date: Oct 2012
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Thumbs up rename node name using xslt and c#

Hi,

I have an array of xml nodes in c# which i pass it to xslt along with newnodename. I need to rename all the oldnodename with newnodename.
Code:
 XmlReader oXmlReader = XmlReader.Create(new StringReader(xmlDoc.InnerXml.ToString()));
XPathDocument oXmlDoc = new XPathDocument(oXmlReader);
XPathNavigator oXmlNav = oXmlDoc.CreateNavigator();

XsltArgumentList argsList = new XsltArgumentList();
argsList.AddParam("newnodename", "", newName);
argsList.AddParam("oldnodename", "", oldNodeName);

XslCompiledTransform transform = new XslCompiledTransform(true);
transform.Load(Server.MapPath("~/App_Data/NodeRename.xslt"));

string outputpath = @"C:\test\output.xml";
using (StreamWriter sw1 = new StreamWriter(outputpath))
{
    transform.Transform(oXmlNav, argsList, sw1);
}
my xslt is something like this
Code:
 
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
  <xsl:param name="newnodename"/>
  <xsl:param name="oldnodename"/>
    <!-- identity transform -->
    <xsl:template match="@* | node()">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:template>

    <!-- rename all nodes called oldnodename -->
    <xsl:template match="/">
      <xsl:choose>
        <xsl:when test="local-name()=@oldnodename">
          <xsl:element
               name="{@newnodename}">
            <xsl:apply-templates select="@*|node()"/>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:element name="{name()}">
            <xsl:apply-templates select="@*|node()"/>
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>

    </xsl:template>
</xsl:stylesheet>
How do i loop xslt to rename all the oldnodenames?
Thank you,
balaji
 
Old March 24th, 2013, 05:41 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

You've started on the right lines by defining an identity template rule that copies nodes unchanged by default. Then you just need to add a rule for nodes that match oldname. In XSLT 2.0 you can write:

Code:
<xsl:template match="*[local-name()=$oldname]>
  <xsl:element name="$newname">
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>
Unfortunately Microsoft's XSLT processor doesn't support XSLT 2.0, and XSLT 1.0 doesn't allow variable references in match patterns. As Microsoft's XML technology is now years behind the latest standards you would be better off moving to third-party tools - both Saxon and XmlPrime support the 2.0 standard on .NET. But if you don't want to do that a workaround would be to define a key:

Code:
<xsl:key name="k" match="*[local-name()=$oldname]" use="1"/>
and then use the key in the match pattern:

Code:
<xsl:template match="key('k', 1)">
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
The Following User Says Thank You to mhkay For This Useful Post:
jminatel (March 26th, 2013)
 
Old March 29th, 2013, 04:49 AM
Registered User
 
Join Date: Oct 2012
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default Thank you very much

Quote:
Originally Posted by mhkay View Post
You've started on the right lines by defining an identity template rule that copies nodes unchanged by default. Then you just need to add a rule for nodes that match oldname. In XSLT 2.0 you can write:

Code:
<xsl:template match="*[local-name()=$oldname]>
  <xsl:element name="$newname">
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>
Unfortunately Microsoft's XSLT processor doesn't support XSLT 2.0, and XSLT 1.0 doesn't allow variable references in match patterns. As Microsoft's XML technology is now years behind the latest standards you would be better off moving to third-party tools - both Saxon and XmlPrime support the 2.0 standard on .NET. But if you don't want to do that a workaround would be to define a key:

Code:
<xsl:key name="k" match="*[local-name()=$oldname]" use="1"/>
and then use the key in the match pattern:

Code:
<xsl:template match="key('k', 1)">
Thank you very much for the reply.As this method is consuming more time to process and my requirement is to rename all the node name which has _ in them to new name. Since passing a whole bunch of new name and old name is there any way i can strip the char right of _ present in a node name and leave the left side of the name as the new node name? e.g. abc_2013 to be renamed as abc. Can i ask a follow up question or need to post it separatly? Thank you once again.
 
Old March 29th, 2013, 04:58 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Try xsl:element name="{substring-before(local-name(), '_'))"

But it won't be any faster!

I can't see any reason why there should be a performance problem for this kind of transformation - it should run at parsing speed.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference





Similar Threads
Thread Thread Starter Forum Replies Last Post
XSLT for getting all node values tsbalaji XSLT 4 October 28th, 2012 09:13 AM
reading the node name using XPATH and XSLT dandagopi XSLT 1 March 2nd, 2012 06:07 PM
changing output for one node in XSLT shane_carty XSLT 3 February 27th, 2008 05:28 AM
modifying a node in xslt the rail dale XSLT 3 July 17th, 2007 09:15 AM
Rename node name venutm XML 0 March 9th, 2006 03:36 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.