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 April 19th, 2012, 09:04 AM
Authorized User
 
Join Date: Jan 2012
Posts: 17
Thanks: 7
Thanked 0 Times in 0 Posts
Default result-document output problem(s) in an identity transform

Hi all -- thanks in advance for any suggestions you might have. I'm having some trouble using
Code:
xsl:result-document
in an identity transform. I'm not sure if it's a problem with my use of
Code:
xsl:copy
, or something else.

Here is a sample XML:
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <row>
        <id>001</id>
        <title>title1</title>
        <author>author2</author>
    </row>
</root>
Here is a sample stylesheet:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output method="xml" indent="yes" standalone="no"/>
    <xsl:variable name="fileName" select="concat(/root/row/id, '.xml')"/>
    
    <xsl:template match="node() | @*">
        <!--<xsl:result-document href="{$fileName}">-->
            <xsl:copy>
                <xsl:apply-templates select="node() | @*"/>
            </xsl:copy>
        <!--</xsl:result-document>-->
    </xsl:template>
    
    <xsl:template match="author">
        <creator>
            <xsl:apply-templates/>
        </creator>
    </xsl:template>
</xsl:stylesheet>
Note: I've commented out the result-document for testing in oXygen (Saxon-HE 9.3.0.5).

When I uncomment the result-document, I get the following error output from Saxon 9.1.0.8J:
Code:
schspanner:xsl canofbees$ saxon -t -s:result-doc-test-1.xml -xsl:result-doc-test-1.xsl
Saxon 9.1.0.8J from Saxonica
Java version 1.6.0_31
Stylesheet compilation time: 262 milliseconds
Processing file:/Users/canofbees/Documents/dli-work/xsl/result-doc-test-1.xml
Building tree for file:/Users/canofbees/Documents/dli-work/xsl/result-doc-test-1.xml using class net.sf.saxon.tinytree.TinyBuilder
Tree built in 2 milliseconds
Tree size: 16 nodes, 16 characters, 0 attributes
Loading net.sf.saxon.event.MessageEmitter
Writing to file:/Users/canofbees/Documents/dli-work/xsl/001.xml
Error at xsl:copy on line 12 of result-doc-test-1.xsl:
  XTDE1490: Cannot write more than one result document to the same URI:
  file:/Users/canofbees/Documents/dli-work/xsl/001.xml
  at xsl:apply-templates (file:/Users/canofbees/Documents/dli-work/xsl/result-doc-test-1.xsl#13)
     processing /root/text()[1]
  in built-in template rule
Transformation failed: Run-time errors were reported
Is the problem using the
Code:
xsl:copy
-- I see the /root/text() error, but I'm not quite sure how to interpret it. Thanks very much for your time.
 
Old April 19th, 2012, 09:08 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

If you want a single result document then put the xsl: result-document in a template that is applied one time. Currently you have it in the identity transformation template that matches a lot of nodes and that way your code asks the XSLT processor to create the same document several times, that is not possible.
If you still have problems, then explain in detail which output document(s?) you want for the input sample you have posted.
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
The Following User Says Thank You to Martin Honnen For This Useful Post:
CanOfBees (April 19th, 2012)
 
Old April 19th, 2012, 09:45 AM
Authorized User
 
Join Date: Jan 2012
Posts: 17
Thanks: 7
Thanked 0 Times in 0 Posts
Default

Hi Martin -- thank you kindly for the response. I'm afraid you've hit upon a significant gap in my XSLT knowledge... well, *one* of the many gaps I should say.

I am taking an XML document (named orig-export-001.xml):
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <row>
        <id>001</id>
        <title>title1</title>
        <author>author2</author>
    </row>
</root>
and transforming it to a new XML document (named 001.xml):
Code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
    <row>
        <id>001</id>
        <title>title1</title>
        <creator>author2</creator>
    </row>
</root>
In the samples above, <author> becomes <creator> in the new file. I don't seem to be able to perform the modified identity transform with your suggestion. I've modified the initial stylesheet as follows. This is successful in that it writes a new XML document with the correct name, but I'm losing the structure of the XML document using this approach. I think that I could add templates for a number of the nodes in the original documents (which are, of course, much more complicated than the given example), but I'm certain I would run into a number of other issues if I try that method.

Code:
<xsl:template match="/">
        <xsl:result-document href="{$fileName}">
            <xsl:copy>
                <xsl:apply-templates select="node() | @*"/>
            </xsl:copy>
        </xsl:result-document>
    </xsl:template>
Thanks again for your time & trouble.
 
Old April 19th, 2012, 09:56 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Firstly you don't need xsl:result-document if you are only producing one output. You can use it if you like, but don't run before you can walk.

This is a simple "modified identity" transformation. Use one template rule to copy elements unchanged:

Code:
<xsl:template match="*">
  <xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>
and another rule to define the exception:

Code:
<xsl:template match="author">
  <creator><xsl:value-of select="."/></creator>
</xsl:template>
(Note I have used a simplfied form of the identity template which is possible because you don't have any attributes.)
__________________
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:
CanOfBees (April 19th, 2012)
 
Old April 19th, 2012, 10:09 AM
Friend of Wrox
 
Join Date: Nov 2007
Posts: 1,243
Thanks: 0
Thanked 245 Times in 244 Posts
Default

I agree with Mike, as long as you don't want to produce several result files you don't need xsl: result-document at all, you can simply create the result elements and then use the XSLT processor's command line options to make sure the transformation result is written to the file destination you want.
If you need or want to name the output in the transformation then use e.g.
Code:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output method="xml" indent="yes" standalone="no"/>
    <xsl:variable name="fileName" select="concat(/root/row/id, '.xml')"/>
    
    <xsl:template match="/">
      <xsl:result-document href="{$fileName}">
        <xsl:apply-templates/>
      </xsl:result-document>
    </xsl:template>

    <xsl:template match="node() | @*">
       <xsl:copy>
                <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="author">
        <creator>
            <xsl:apply-templates/>
        </creator>
    </xsl:template>
</xsl:stylesheet>
__________________
Martin Honnen
Microsoft MVP (XML, Data Platform Development) 2005/04 - 2013/03
My blog
The Following User Says Thank You to Martin Honnen For This Useful Post:
CanOfBees (April 19th, 2012)
 
Old April 19th, 2012, 10:39 AM
Authorized User
 
Join Date: Jan 2012
Posts: 17
Thanks: 7
Thanked 0 Times in 0 Posts
Default

Hi Michael -- thank you for the response -- it's a reminder that I need to be more mindful of how I'm expressing myself here on the web. My apologies for the oversight.

I'm processing a directory of XML files; e.g. orig-export-001.xml, orig-export-002.xml, ..., orig-export-143.xml. I'm writing the output files (with new names) to a different directory for additional processing.

Is there a different method for writing files out with new names and incorporating the "modified identity" transformation?

PS I'm feeling as though I should move back to crawling -- walking is... difficult at times.

EDIT -- Martin, thank you very much. That's exactly what I need. I tried something almost-similar, but it was still miles off the mark. Cheers!

Last edited by CanOfBees; April 19th, 2012 at 10:45 AM.. Reason: Reacting to Martin's response
 
Old April 19th, 2012, 10:53 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Are you running one transformation per input file, or are you processing all the input files using a single call of the XSLT processor?
__________________
Michael Kay
http://www.saxonica.com/
Author, XSLT 2.0 and XPath 2.0 Programmer\'s Reference
 
Old April 19th, 2012, 10:57 AM
Authorized User
 
Join Date: Jan 2012
Posts: 17
Thanks: 7
Thanked 0 Times in 0 Posts
Default

I *think* that I'm using one call to the processor; e.g.:

Code:
$ saxon -s:ead-processing-20120328/0exportOriginals -xsl:at-output-cleanup.xsl -o:ead-processing-20120328/1AT-outputProcessedNewNames/
To be honest, though, I'm not quite sure. It seems like the above would process all of the input files, but this is far outside of my understanding.

Last edited by CanOfBees; April 19th, 2012 at 11:00 AM.. Reason: Formatting
 
Old April 19th, 2012, 11:12 AM
mhkay's Avatar
Wrox Author
 
Join Date: Apr 2004
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

OK, internally that's doing one transformation per input file. It's designed to write the result of that transformation to a file in the output directory that has the same name as the input file. You can use xsl:result-document to write output somewhere else, if you want, but it's then your job to make the output file names unique.

Your original problem was that you were creating a result document for each node in each input document. If you use result-document at the level of the match="/" template, that problem goes away.
__________________
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:
CanOfBees (April 20th, 2012)
 
Old April 20th, 2012, 09:30 AM
Authorized User
 
Join Date: Jan 2012
Posts: 17
Thanks: 7
Thanked 0 Times in 0 Posts
Default

Michael & Martin -- thanks again for the assistance!





Similar Threads
Thread Thread Starter Forum Replies Last Post
Namespace problems in an identity transform CanOfBees XSLT 2 April 17th, 2012 09:38 AM
identity transform excluding xml element ShaileshShinde BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition ISBN: 978-0-470-19274-0 1 November 2nd, 2011 09:22 AM
XSL sort on identity transform imshriram XSLT 1 October 14th, 2011 03:57 PM
Split xml file with result document and javax.xml.transform.Transformer. nisargmca XSLT 3 January 12th, 2010 06:26 AM
Getting @@IDENTITY in Row Transform afward SQL Server DTS 2 September 28th, 2005 09:56 AM





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