[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Re: How to handle dynamic XPath

Subject: Re: Re: How to handle dynamic XPath
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Mon, 13 Apr 2009 06:50:44 -0700
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
>>> ***********************************

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.