By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,463 Members | 2,858 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,463 IT Pros & Developers. It's quick & easy.

XSLT and document()/Node

P: n/a
Hello,

I've got a problem. Either I have missed the most important point or
it really does not work:

I want to use the document function with an absolut path on WindowsXP
Professional and Saxon 8.1. However, retrieving a subnode of the
documents content is not possible. Inserting a whole document result
set is functional, subset not. Example:

001 <?xml version="1.0"?>
002 <xsl:stylesheet version="1.1"
003 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
004 <xsl:param name="files" select="''"/>
005 <xsl:template match="/">
006 <Service>
007 <xsl:call-template name="concatenateFiles">
008 <xsl:with-param name="theFiles"
009 select="concat(normalize-space($files), ' ')"/>
010 </xsl:call-template>
011 </Service>
012 </xsl:template>
013
014 <xsl:template name="concatenateFiles">
015 <xsl:param name="theFiles"/>
016 <xsl:variable name="file"
017 select="substring-before($theFiles, ' ')"/>
018 <xsl:copy-of select="document($file)/Service/Output"/>
019 <xsl:variable name="rest"
020 select="substring-after($theFiles, ' ')"/>
021 <xsl:if test="$rest">
022 <xsl:call-template name="concatenateFiles">
023 <xsl:with-param name="theFiles" select="$rest"/>
024 </xsl:call-template>
025 </xsl:if>
026 </xsl:template>
027 </xsl:stylesheet>

Passing an existing file to the "files" parameter does not work at
all. A simple <Service/> is returned. Reducing line 021 to

018 <xsl:copy-of select="document($file)"/>

does work, however doesn't achive the desired result to incorporate
just a subnode of the document loaded.

I am thankful for any hints in this concern.

Daniel Frey
Jul 20 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a

018 <xsl:copy-of select="document($file)/Service/Output"/> 018 <xsl:copy-of select="document($file)"/>
does work,


presumably your documents don't have top level element Service with
children Output (perhaps they have elements in some namespace?)

Incidentally since you are using saxon 8 and so xslt2 you needn't step
through that space separated list of filenames using recursion on
substring; you can coerce it directly to a sequence of strings and then
iterate over the sequence.

David
Jul 20 '05 #2

P: n/a
Thanks for your reply. The xml in question has got a <Service> element.
And your right, there is a namespace in the element.

The abstracted xml source look like this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Service xmlns="uri://bw.ubs.com/map">
<Header ...>
<Status ...>
<Output ...>
</Service>

How do I address the nodes in a namespace attributed element?

I do not understand the other hint you gave me completely. Can you give
a small sample of "coercing" the string list directly?

Thank you for your help.

Daniel Frey

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Jul 20 '05 #3

P: n/a

an Xpath of /Service/... matches the element with empty namespace URI
and local name Service, you want to match an element with namespace URI
uri://bw.ubs.com/map and local name Service (incidentally I don't think
there is a registered uri scheme of uri: is there? Not that The
Namespace spec cares if the namespace URI is valid as a URI.

In XSLT1 (and this also works in 2) you need to use prefixed expressions
in the xpath, stick
xmlns:x="uri://bw.ubs.com/map"
on your xsl:stylesheet and then use
/x:Service/x:Output

(You don't need to change your source documents)

Since you are using the XSLT2 draft you could instead change the default
Xpath element name namespace by putting
xpath-default-namespace="uri://bw.ubs.com/map"
on your xsl:stylesheet element, but that will affect _all_ Xpath's in
the stylesheet so if some of your input is not in that namespace this
might not be what you want.
I do not understand the other hint you gave me completely. Can you give
a small sample of "coercing" the string list directly?


You could use the as attribute on the xsl:param to force it to be
interpretted as a sequence of strings, or more explictly, gven the white
space separated string you could do

<xsl:for-each select="tokenize($files,'\s+')">
<xsl:copy-of select="doc(.)/....

see
http://www.w3.org/TR/xquery-operators/#func-tokenize
David
Jul 20 '05 #4

P: n/a
Thank you very much David. I copied the namespace solution, perfect! The
tokenize solution is also easy to understand. It simplifies the
stylesheet enormously!

However, I get an exception in saxon 8.1 driver when running the code.
The stylesheet looks now like this:

001 <?xml version="1.0"?>
002 <xsl:stylesheet version="1.1"
003 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
004 xmlns:u="uri://bw.ubs.com/map">
005 <xsl:output indent="yes"/>
006 <xsl:param name="files" select="''"/>
007 <xsl:template match="/">
008 <Service>
009 <xsl:for-each select="tokenize($files,'\s+')">
010 <xsl:copy-of select="document(.)/u:Service"/>
011 </xsl:for-each>
012 </Service>
013 </xsl:template>
014 </xsl:stylesheet>

But line 009 throws a ClassCastException.

java.lang.RuntimeException: net.sf.saxon.value.StringValue
java.lang.ClassCastException: net.sf.saxon.value.StringValue
at
com.exln.stylus.CSaxon8Driver.startCurrentItem(CSa xon8Driver.java:1100)
at net.sf.saxon.instruct.ForEach.processLeavingTail(F orEach.java:125)
at net.sf.saxon.instruct.Instruction.process(Instruct ion.java:91)
at
net.sf.saxon.instruct.TraceWrapper.processLeavingT ail(TraceWrapper.java:
79)
at net.sf.saxon.instruct.Instruction.process(Instruct ion.java:91)
at
net.sf.saxon.instruct.InstructionWithChildren.proc essChildren(Instructio
nWithChildren.java:158)
at
net.sf.saxon.instruct.ElementCreator.processLeavin gTail(ElementCreator.j
ava:122)
at net.sf.saxon.instruct.Instruction.process(Instruct ion.java:91)
at
net.sf.saxon.instruct.TraceWrapper.processLeavingT ail(TraceWrapper.java:
79)
at
net.sf.saxon.instruct.InstructionWithChildren.proc essChildrenLeavingTail
(InstructionWithChildren.java:196)
at net.sf.saxon.instruct.Block.processLeavingTail(Blo ck.java:117)
at net.sf.saxon.instruct.Instruction.process(Instruct ion.java:91)
at
net.sf.saxon.instruct.TraceWrapper.processLeavingT ail(TraceWrapper.java:
79)
at net.sf.saxon.instruct.Template.expand(Template.jav a:98)
at net.sf.saxon.instruct.Template.processLeavingTail( Template.java:82)
at
net.sf.saxon.instruct.ApplyTemplates.applyTemplate s(ApplyTemplates.java:
226)
at net.sf.saxon.Controller.transformDocument(Controll er.java:1094)
at net.sf.saxon.Controller.transform(Controller.java: 940)
at com.exln.stylus.CSaxon8Driver.doProcessing(CSaxon8 Driver.java:169)
at com.exln.stylus.CProcessorDriver.process(CProcesso rDriver.java:55)
The parameter passed (without line breaks) is

C:/DOKUME~1/DANIEL~1/LOKALE~1/Temp/test42553/workflow/work42555.2
C:/DOKUME~1/DANIEL~1/LOKALE~1/Temp/test42553/workflow/work42555.4
C:/DOKUME~1/DANIEL~1/LOKALE~1/Temp/test42553/workflow/work42555.6

But I still have the fallback solution I used before. Anyway, a big
thank you for your help!

Daniel Frey

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Jul 20 '05 #5

P: n/a

If you get a java exception raised by saxon (or any xslt engine) 'tis a
bug in the processor. If you pass that on to Michael at saxon's help
email address I'm sure he'll look at it.

I'm surprised that saxon's document() function accepts
C:/DOKUME~1/DANIEL~1/LOKALE~1/Temp/test42553/workflow/work42555.2
(however you split that off your string) as it is supposed to be a URI
and C: isn't known uri scheme (which needs to be file: or http: or ftp:
or some such) that should be
file:///C:/DOKUME~1/DANIEL~1/LOKALE~1/Temp/test42553/workflow/work42555.2
however I doubt that is the cause of your exception.

David
Jul 20 '05 #6

P: n/a
> <xsl:copy-of select="document($file)"/>

does work, however doesn't achive the desired result to incorporate
just a subnode of the document loaded.


Hi,

try: 'document($file)//Service' in stead of 'document($file)/Service'. In practical situations, I've epercienced that '/' fails to work when handling a document node. I'm not sure why, though.

regards,
--
Joris Gillis (http://www.ticalc.org/cgi-bin/acct-v...i?userid=38041)
Ceterum censeo XML omnibus esse utendum
Jul 20 '05 #7

P: n/a
"Joris Gillis" <ro**@pandora.be> writes:
try: 'document($file)//Service' in stead of
'document($file)/Service'. In practical situations, I've epercienced
that '/' fails to work when handling a document node. I'm not sure
why, though.

regards,


If you know that Service is the top level element then // is an
expensive thing to try since it tells the system to search the entire
document to arbitrary depth looking for all Service' elements.

If Service' is not the top level element then clearly /Service won't
work but its usually better to use a more explict path than // so as to
limit searching, eg /*/Service if it's a second level element.

David
Jul 20 '05 #8

P: n/a
In my case it is not suitable to use //Service as the Output element
contains another Service element which should not be incorporated. And I
have the impression that this would not solve the namespace issue, would
it? In my case I would use something like //u:Service to address all
Service elements, wouldn't I?

Daniel

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Jul 20 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.