 |
| 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
|
|
|
|

March 16th, 2011, 11:27 AM
|
|
Authorized User
|
|
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
|
|
Copy entire XML except, but change a few nodes...
I'm trying to copy the content of an XML, with the exception of replacing a few of the attributes in that XML.
I'm using XSLT 1.0.
So, here's my XML
XML Sample (sample.xml)
Code:
<?xml version="1.0" encoding="UTF-8"?>
<main>
<date/>
<time/>
<clients>
<domestic>
<client id = "1" name = "sample" abbreviation = "sp"/>
</domestic>
<foreign>
<client id = "7" name = "sampling" abbreviation = "sping"/>
</foreign>
</clients>
<clients>
<domestic>
<client id = "4" name = "example" abbreviation = "ex"/>
</domestic>
<foreign>
<client id = "3" name = "test" abbreviation = "tst"/>
</foreign>
<clients>
<clients>
<domestic>
<client id = "3" name = "test" abbreviation = "tst"/>
</domestic>
<foreign>
<client id = "7" name = "sampling" abbreviation = "dm"/>
</foreign>
<clients>
<clients>
<domestic>
<client id = "12" name = "sample" abbreviation = "sping"/>
</domestic>
<foreign>
<client id = "2" name = "case" abbreviation = "cs"/>
</foreign>
<clients>
etc...
</main>
XML with translations (translations.xml)
Code:
<?xml version="1.0" encoding="UTF-8"?>
<main>
<date/>
<time/>
<clients>
<client id = "1" name = "random"/>
<client id = "2" name = "anything"/>
<client id = "3" name = "whatever"/>
<client id = "4" name = "replace"/>
<client id = "7" name = "different"/>
<client id = "12" name = "change"/>
etc...
<clients>
</main>
Desired result (new_sample.xml)
Code:
<?xml version="1.0" encoding="UTF-8"?>
<main>
<date/>
<time/>
<clients>
<domestic>
<client id = "1" name = "random" abbreviation = "sp"/>
</domestic>
<foreign>
<client id = "7" name = "different" abbreviation = "sping"/>
</foreign>
</clients>
<clients>
<domestic>
<client id = "4" name = "replace" abbreviation = "ex"/>
</domestic>
<foreign>
<client id = "3" name = "whatever" abbreviation = "tst"/>
</foreign>
<clients>
<clients>
<domestic>
<client id = "3" name = "whatever" abbreviation = "tst"/>
</domestic>
<foreign>
<client id = "7" name = "different" abbreviation = "dm"/>
</foreign>
<clients>
<clients>
<domestic>
<client id = "12" name = "change" abbreviation = "sping"/>
</domestic>
<foreign>
<client id = "2" name = "anything" abbreviation = "cs"/>
</foreign>
<clients>
etc...
</main>
What I'm trying to do is copy the content of sample.xml, however, I'd like to replace the name attribute values in it with the values from translation.xml. I know how to copy the content of an entire xml (copy-of select="/"), however, i'm not sure how to replace attribute values in these instances.
Last edited by vb89; March 16th, 2011 at 11:31 AM..
|
|

March 16th, 2011, 11:45 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
>I'm trying to copy the content of an XML, with the exception of replacing a few of the attributes in that XML.
That's a classic case for the "modified identity transform" pattern. You need one rule that copies everything:
Code:
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
and another rule for the exceptions:
Code:
<xsl:template match="client/@name">
<xsl:attribute name="name" select="document('translations.xml')//client[@id=current()/../@id]/@name"/>
</xsl:template>
You could speed it up with a key for the lookup.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

March 16th, 2011, 11:47 AM
|
 |
Wrox Author
|
|
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
|
|
Sorry, the select attribute of xsl:attribute is XSLT 2.0 - you'll need a nested xsl:value-of child for 1.0.
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
|
|

March 16th, 2011, 12:09 PM
|
|
Authorized User
|
|
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
|
|
Thanks mhkay, I greatly appreciate it. Can you possibly provide some pseudo/sample code of how to use nested xsl:value-of child?
|
|

March 16th, 2011, 12:27 PM
|
|
Authorized User
|
|
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
|
|
Quote:
Originally Posted by mhkay
Sorry, the select attribute of xsl:attribute is XSLT 2.0 - you'll need a nested xsl:value-of child for 1.0.
|
Actually, did you just mean "<xsl:value-of select=".."/>"?
|
|

March 16th, 2011, 01:09 PM
|
|
Authorized User
|
|
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
|
|
Michael,
I tried to use the code that you suggested, however, I'm getting the following exception:
"node() in step pattern not implemented"
Here's my XSL:
Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="no" omit-xml-declaration="yes"/>
<xsl:variable name="vLeague_Name"><xsl:value-of select="//league/@alias"/></xsl:variable>
<xsl:variable name="vClient_ID">4</xsl:variable>
<xsl:variable name="tFilename" select="concat('translations.XML')"/>
<xsl:variable name="tClientXlate" select="document($tFilename)"/>
<xsl:template match="node()|@*">&newline;
<outputfile>new_sample.XML</outputfile>&newline;
<xsl:text disable-output-escaping="yes"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>]]></xsl:text>&newline;
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="team-info/@abbrev">
<xsl:attribute name="alias"><xsl:value-of select="$tClientXlate//client[@id=$vClient_ID]/@abbrev"/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Last edited by vb89; March 16th, 2011 at 01:59 PM..
|
|

March 16th, 2011, 01:15 PM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
Which XSLT processor gives that error message? Do you get the exact line indicated causing that error?
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

March 16th, 2011, 01:21 PM
|
|
Authorized User
|
|
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
|
|
I'm using XT - Error at line 36 (<xsl:template match="node()|@*">&newline; )
I tried using NXSLT and I got the following error: "Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added." NXSLT didn't show a line number, but i assume it alluded to the same thing.
|
|

March 16th, 2011, 01:30 PM
|
|
Friend of Wrox
|
|
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
|
|
I don't know XT and whether it is a complete XSLT 1.0 implementation. The match="node()|@*" is fine in my view.
The error message by NXSLT relates to other code, for reasons I don't understand and surely not suggested by Michael Kay you have put additional code into the identity transformation template that will cause problems.
If you want the result document to be serialized with an XML declaration then simply use
Code:
<xsl:output method="xml" omit-xml-declaration="no"/>
, that way you don't need that CDATA section hack.
And you might want to output an "outputfile" element but surely not for every node and attribute the identity transformation template processes so remove that line as well. If you have an element you want to add an "outputfile" element to then write an additonal template for that e.g.
Code:
<xsl:template match="foo">
<outputfile>...</outputfile>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
If you still have problems then explain where you want to add that "outputfile" element, then we can help with proper code.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
|
|

March 16th, 2011, 01:44 PM
|
|
Authorized User
|
|
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
|
|
Martin,
XT is an implementation in Java of XSL Transformations ( http://www.jclark.com/xml/xt-old.html)
In regard to the output file, no, I don't want to output the "output" element after each node/attribute, I just want to output it at the beginning of the file once.
And after using NXSLT again, I read the details and it appear to throw an exception at the same line:
<xsl:template match="node()|@*">&newline;
|
|
 |