[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
At 2009-04-12 21:07 +0200, fred@xxxxxxxxxxxxx wrote:
I'm assuming the structures of the two documents are identical.
Correct, because there is no such thing as "eval()" in XPath. The final step of your XPath address is the value of a variable, so you are getting the value of the variable as you should.
And who is to say that your prefixes in your input document match the prefixes in your default value document?
I would expect you to see the string "rsm:DeliveryDate", not nothing.
You could use a key table, where the lookup value for each element is that element's fully-qualified XPath address. And you could use the "{namespace-uri}local-name" syntax for each element in the path in order to be independent of namespace prefixes.
Then you use:
and it will return the value of the element.
You don't give any sample data to test with, and you don't talk about sibling elements of the same name, but I think this approach would work for you. An example is below where each element of fred.xml is replaced with the corresponding value from fred-default.xml.
I hope this helps.
. . . . . . . . . . . . . Ken
<xsl:key name="paths" match="*" use="f:make-path(.)"/>
</xsl:stylesheet>
T:\ftemp>rem Done!
Re: [xsl] How to handle dynamic XPath
Subject: Re: [xsl] How to handle dynamic XPath From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx> Date: Sun, 12 Apr 2009 15:34:14 -0400 |
At 2009-04-12 21:07 +0200, fred@xxxxxxxxxxxxx wrote:
I am using XSLT to walk through an XML Schema to construct an Xforms (output) instance. In parallel I am scanning an (input) instance (of a document defined by the schema) to include default values in the form.
I'm assuming the structures of the two documents are identical.
Scanning of the input instance is done by means of a variable that keeps track of the path. The variable is updated (renewed) each time a template is (recursively) called with the variable as parameter:
<xsl:with-param name="instance.path" select="concat($instance.path,'/',$element.prefix,':',@name)" />
The template calls another template that writes the output instance. In that template I try to look up the default value in the input instance (an external document).
BUT:
<xsl:value-of select="document('file:/C:/dir/order.xml')/$instance.path" /> writes a path string to the output instance instead of the value of the element, such as: /rsm:PurchaseOrder/rsm:Identifier, so does copy-of select.
Correct, because there is no such thing as "eval()" in XPath. The final step of your XPath address is the value of a variable, so you are getting the value of the variable as you should.
And who is to say that your prefixes in your input document match the prefixes in your default value document?
<xsl:value-of select="document('file:/C:/dir/order.xml')//rsm:DeliveryDate" /> writes correctly the content of the delivery date, but <xsl:value-of select="document('file:/C:/dir/order.xml')//$deldate" /> (where $deldate contains the string "rsm:DeliveryDate") writes nothing.
I would expect you to see the string "rsm:DeliveryDate", not nothing.
Concluding the problem is node-format vs text format, I tried the saxon evaluate function, but: <xsl:copy-of select="saxon:evaluate(document('file:/C:/dir/order.xml')/$instance.path)" /> writes nothing, neither does value-of.
I am desperate. Does anyone have a clue how to solve this?
You could use a key table, where the lookup value for each element is that element's fully-qualified XPath address. And you could use the "{namespace-uri}local-name" syntax for each element in the path in order to be independent of namespace prefixes.
Then you use:
<xsl:value-of select="document('file:/C:/dir/order.xml')/ key('myTable',$instance.path))"/>
and it will return the value of the element.
You don't give any sample data to test with, and you don't talk about sibling elements of the same name, but I think this approach would work for you. An example is below where each element of fred.xml is replaced with the corresponding value from fred-default.xml.
I hope this helps.
. . . . . . . . . . . . . Ken
T:\ftemp>type fred.xml <a xmlns="urn:x-fred"> <b>B1</b> <c>C1</c> <b>B2</b> <d> <e>E1</e> </d> </a> T:\ftemp>type fred-default.xml <f:a xmlns:f="urn:x-fred"> <f:b>def-B1</f:b> <f:c>def-C1</f:c> <f:b>def-B2</f:b> <f:d> <f:e>def-E1</f:e> </f:d> </f:a> T:\ftemp>call xslt2 fred.xml fred.xsl <?xml version="1.0" encoding="UTF-8"?><a xmlns="urn:x-fred"> <b>def-B1</b> <c>def-C1</c> <b>def-B2</b> <d> <e>def-E1</e> </d> </a> T:\ftemp>type fred.xsl <?xml version="1.0" encoding="US-ASCII"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="urn:x-fred" version="2.0">
<xsl:key name="paths" match="*" use="f:make-path(.)"/>
<!--walk the element tree--> <xsl:template match="*"> <xsl:param name="path"/> <!--determine the path to this element--> <xsl:variable name="this-path" select="concat($path,f:make-step(.))"/> <!--preserve the element structure--> <xsl:copy> <!--preserve any attributes--> <xsl:apply-templates select="@*"/> <!--replace the value when there are no element children--> <xsl:choose> <xsl:when test="not(*)"> <!--at a leaf element--> <xsl:value-of select="document('fred-default.xml')/ key('paths',$this-path)"/> </xsl:when> <xsl:otherwise> <!--at a branch element, keep going--> <xsl:apply-templates> <xsl:with-param name="path" select="$this-path"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </xsl:copy> </xsl:template>
<!--identity for all other nodes--> <xsl:template match="@*|comment()|processing-instruction()"> <xsl:copy/> </xsl:template>
<!--create a lookup key--> <xsl:function name="f:make-path"> <xsl:param name="element"/> <xsl:sequence select="string-join( for $e in $element/ancestor-or-self::* return f:make-step( $e ), '' )"/> </xsl:function>
<xsl:function name="f:make-step"> <xsl:param name="element"/> <xsl:for-each select="$element"> <xsl:sequence select="concat('/{',namespace-uri(.),'}',local-name(.), '[',count(preceding-sibling::*[node-name(.)=node-name(current())])+1, ']')"/> </xsl:for-each> </xsl:function>
</xsl:stylesheet>
T:\ftemp>rem Done!
-- XSLT/XSL-FO/XQuery training in Los Angeles (New dates!) 2009-06-08 Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video Video lesson: http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18 Video overview: http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18 G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/ Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/s/bc Legal business disclaimers: http://www.CraneSoftwrights.com/legal
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Re : [xsl] How to handle dyna, Florent Georges | Thread | RE: [xsl] How to handle dynamic XPa, Michael Kay |
[xsl] Re : [xsl] How to handle dyna, Florent Georges | Date | RE: [xsl] How to handle dynamic XPa, Michael Kay |
Month |
Keywords