Subject: Re: [xsl] Re: How to handle dynamic XPath From: Dimitre Novatchev <dnovatchev@xxxxxxxxx> Date: Mon, 13 Apr 2009 06:46:49 -0700 |
> Mike's solution works, although I would prefer a solution without extension > functions. One could use the FXSL LR-Parsing framework to create an XPath parser. This is what I did more than an year ago (an XPath 2.0) parser, and already forgot about it -- could find no use for it until recently, when Florent asked for the parser with the intent to use it for hi-lighting XPath expressions. Another use could be to convert a complicated XPath expression into corresponding equivalent XSLT instructions -- for people who prefer the XSLT-oriented syntax over the XPath-oriented one. Or, if we could use the XPath 2.0 grammer to *synthesize* XPath expressions, then one could create an app. to convert XSLT to an XPath expression. Anyone heard of a usable instance generator, as opposed to a parser, using a grmmar definition? -- Cheers, Dimitre Novatchev --------------------------------------- Truly great madness cannot be achieved without significant intelligence. --------------------------------------- To invent, you need a good imagination and a pile of junk ------------------------------------- Never fight an inanimate object ------------------------------------- You've achieved success in your field when you don't know whether what you're doing is work or play On Sun, Apr 12, 2009 at 11:28 PM, <fred@xxxxxxxxxxxxx> wrote: > This list is incredible! > I was struggling all Easter sunday with a problem, posted it, went to sleep > and overnight three experts came with solutions. Thank you, Ken, Michael and > Florent! > > Mike's solution works, although I would prefer a solution without extension > functions. > Keeping a key table as Ken suggests is a bit difficult, as beforehand > (design time) I do not know the structure of the documents. The XSL takes > any XML schema that obeys certain rules of well-formedness. Creating the key > table at run time could be a solution though. > Florents suggestion of a meta-stylesheet is worth wile investigating, but > that would complicate the application even more. > > Hope I didnt spoil your Easter too much. > > Fred > > > > >> ------------------------------ >> >> Date: Sun, 12 Apr 2009 21:07:29 +0200 >> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx >> From: fred@xxxxxxxxxxxxx >> Subject: How to handle dynamic XPath >> Message-ID: <20090412210729.uv66b6hsw0sgksw0@xxxxxxxxxxxxxxxxxxxxx> >> >> Hi, >> >> I am using XSLT to walk through an XML Schema to construct an Xforms =20 >> (output) instance. >> In parallel I am scanning an (input) instance (of a document defined =20 >> by the schema) to >> include default values in the form. >> >> Scanning of the input instance is done by means of a variable that =20 >> keeps track of the >> path. The variable is updated (renewed) each time a template is =20 >> (recursively) called with >> the variable as parameter: >> >> <xsl:with-param name=3D"instance.path" >> select=3D"concat($instance.path,'/',$element.prefix,':',@name)" /> >> >> The template calls another template that writes the output instance. =20 >> In that template I >> try to look up the default value in the input instance (an external >> document= >> ). >> >> BUT: >> >> <xsl:value-of select=3D"document('file:/C:/dir/order.xml')/$instance.path" >> /= >>> >> writes a path string to the output instance instead of the value of =20 >> the element, such as: >> /rsm:PurchaseOrder/rsm:Identifier, so does copy-of select. >> >> <xsl:value-of >> select=3D"document('file:/C:/dir/order.xml')//rsm:DeliveryDate= >> " /> >> writes correctly the content of the delivery date, but >> <xsl:value-of select=3D"document('file:/C:/dir/order.xml')//$deldate" /> >> (where $deldate contains the string "rsm:DeliveryDate") writes nothing. >> >> Concluding the problem is node-format vs text format, I tried the =20 >> saxon evaluate >> function, but: >> <xsl:copy-of =20 >> >> select=3D"saxon:evaluate(document('file:/C:/dir/order.xml')/$instance.path)"= >> B =20 >> /> >> writes nothing, neither does value-of. >> >> I am desperate. Does anyone have a clue how to solve this? >> >> Thanks in advance, >> >> Fred van Blommestein >> >> ------------------------------ >> >> Date: Sun, 12 Apr 2009 15:34:14 -0400 >> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx >> From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx> >> Subject: Re: [xsl] How to handle dynamic XPath >> Message-Id: <7.0.1.0.2.20090412152437.02699d30@xxxxxxxxxxxxxxxxxxxxxx> >> >> 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 >>> B 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. B 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 >>> B 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. B 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: >> >> B <xsl:value-of select="document('file:/C:/dir/order.xml')/ >> B B B B B B B B B B B B 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. B 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 <b>B1</b> >> B <c>C1</c> >> B <b>B2</b> >> B <d> >> B B <e>E1</e> >> B </d> >> </a> >> T:\ftemp>type fred-default.xml >> <f:a xmlns:f="urn:x-fred"> >> B <f:b>def-B1</f:b> >> B <f:c>def-C1</f:c> >> B <f:b>def-B2</f:b> >> B <f:d> >> B B <f:e>def-E1</f:e> >> B </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 <b>def-B1</b> >> B <c>def-C1</c> >> B <b>def-B2</b> >> B <d> >> B B <e>def-E1</e> >> B </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" >> B B B B B B B B xmlns:f="urn:x-fred" >> B B B B B B B B version="2.0"> >> >> <xsl:key name="paths" match="*" use="f:make-path(.)"/> >> >> <!--walk the element tree--> >> <xsl:template match="*"> >> B <xsl:param name="path"/> >> B <!--determine the path to this element--> >> B <xsl:variable name="this-path" >> B B B B B B B B select="concat($path,f:make-step(.))"/> >> B <!--preserve the element structure--> >> B <xsl:copy> >> B B <!--preserve any attributes--> >> B B <xsl:apply-templates select="@*"/> >> B B <!--replace the value when there are no element children--> >> B B <xsl:choose> >> B B B <xsl:when test="not(*)"> >> B B B B <!--at a leaf element--> >> B B B B <xsl:value-of select="document('fred-default.xml')/ >> B B B B B B B B B B B B B B B key('paths',$this-path)"/> >> B B B </xsl:when> >> B B B <xsl:otherwise> >> B B B B <!--at a branch element, keep going--> >> B B B B <xsl:apply-templates> >> B B B B B <xsl:with-param name="path" select="$this-path"/> >> B B B B </xsl:apply-templates> >> B B B </xsl:otherwise> >> B B </xsl:choose> >> B </xsl:copy> >> </xsl:template> >> >> <!--identity for all other nodes--> >> <xsl:template match="@*|comment()|processing-instruction()"> >> B <xsl:copy/> >> </xsl:template> >> >> <!--create a lookup key--> >> <xsl:function name="f:make-path"> >> B <xsl:param name="element"/> >> B <xsl:sequence select="string-join( for $e in >> $element/ancestor-or-self::* >> B B B B B B B B B B B B B B B B B B B return f:make-step( $e ), '' )"/> >> </xsl:function> >> >> <xsl:function name="f:make-step"> >> B <xsl:param name="element"/> >> B <xsl:for-each select="$element"> >> B B <xsl:sequence select="concat('/{',namespace-uri(.),'}',local-name(.), >> >> B '[',count(preceding-sibling::*[node-name(.)=node-name(current())])+1, >> B B B B ']')"/> >> B </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: B B http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18 >> Video overview: B http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18 >> G. Ken Holman B B B B B B B B mailto:gkholman@xxxxxxxxxxxxxxxxxxxx >> Crane Softwrights Ltd. B B B B B http://www.CraneSoftwrights.com/s/ >> Male Cancer Awareness Nov'07 B http://www.CraneSoftwrights.com/s/bc >> Legal business disclaimers: B http://www.CraneSoftwrights.com/legal >> >> ------------------------------ >> >> Date: Sun, 12 Apr 2009 23:35:31 +0100 >> To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx> >> From: "Michael Kay" <mike@xxxxxxxxxxxx> >> Subject: RE: [xsl] How to handle dynamic XPath >> Message-ID: <4FA95E4459EE4A4B85EEF35A0C54B439@Sealion> >> >>> 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')/$ins >>> tance.path)" >>> /> >>> writes nothing, neither does value-of. >> >> You're on the right lines here, but the syntax would be >> >> select="document('file:/C:/dir/order.xml')/saxon:evaluate($instance.path)" >> >> I strongly suspect that there are much better solutions to this problem >> that >> don't involve dynamic evaluation. However, it's Easter Sunday. >> >> Michael Kay >> http://www.saxonica.com/ >> >> ------------------------------ >> >> Date: Sun, 12 Apr 2009 19:52:19 +0000 (GMT) >> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx >> From: Florent Georges <lists@xxxxxxxxxxxx> >> Subject: Re : [xsl] How to handle dynamic XPath >> Message-ID: <816269.32982.qm@xxxxxxxxxxxxxxxxxxxxxxxxxxx> >> >> fred@xxxxxxxxxxxxx wrote: >> >> B Hi, >> >>> <xsl:with-param name=3D"instance.path" >>> select=3D"concat($instance.path,'/',$element.prefix,':',@name)" >>> /> >> >> B You cannot evaluate an XPath expression supplied as a string in plain >> XSL= >> T. B You can use extensions though for that purpose (of your own or >> existing= >> B one.) B I haven't looked deeply into your problem, but I'd say I'd rather >> u= >> ser either: >> >> B 1/ maintaining a pointer in the instance and selecting its correct >> child(= >> ren) using local-name() and namespace-uri() for each step; >> >> B 2/ or using a meta-stylesheet: your stylesheet generates another XSLT >> sty= >> lesheet that contains the XPath expressions (you "compile" the schema to >> th= >> e equivalent stylesheet) and you apply this stylesheet to the instance in >> a= >> B second execution. >> >> B Regards, >> >> --=20 >> Florent Georges >> http://www.fgeorges.org/ >> >> =0A=0A=0A >> >> ------------------------------ >> >> End of xsl-list Digest >> ***********************************
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Re: How to handle dynamic, G. Ken Holman | Thread | Re: [xsl] Re: How to handle dynamic, Dimitre Novatchev |
Re: [xsl] Re: How to handle dynamic, G. Ken Holman | Date | Re: [xsl] Re: How to handle dynamic, Dimitre Novatchev |
Month |