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 16th, 2011, 11:27 AM
Authorized User
 
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
Default 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..
 
Old March 16th, 2011, 11:45 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

>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
 
Old March 16th, 2011, 11:47 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

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
 
Old March 16th, 2011, 12:09 PM
Authorized User
 
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
Default

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

Quote:
Originally Posted by mhkay View Post
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=".."/>"?
 
Old March 16th, 2011, 01:09 PM
Authorized User
 
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
Default

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..
 
Old March 16th, 2011, 01:15 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

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
 
Old March 16th, 2011, 01:21 PM
Authorized User
 
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
Default

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.
 
Old March 16th, 2011, 01:30 PM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

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
 
Old March 16th, 2011, 01:44 PM
Authorized User
 
Join Date: Sep 2008
Posts: 37
Thanks: 5
Thanked 0 Times in 0 Posts
Default

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;





Similar Threads
Thread Thread Starter Forum Replies Last Post
Copy-of between two nodes scubin XSLT 6 October 22nd, 2009 05:03 PM
Copy entire document after transform macmillan01 XSLT 2 July 13th, 2009 07:28 AM
copy entire row stealthdevil Access VBA 3 December 1st, 2006 11:39 AM
Need to copy all nodes, attributes, and namespaces juaniux XSLT 4 October 22nd, 2004 04:39 PM
onClick change bgcolor of entire row Pallav Javascript How-To 2 October 21st, 2004 12:35 AM





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