[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Re: How to handle dynamic XPath
Finished my reply too-soon. Another major use of an XPath 2.0 parser could be in a refactoring tool, and also adding to Mukuls Lint the so needed XPath expression analysis. -- 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 Mon, Apr 13, 2009 at 6:46 AM, Dimitre Novatchev <dnovatchev@xxxxxxxxx> wrote: >> 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, B <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: 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: 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 : 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 >>> ***********************************
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|