Y
Yarik
Hello,
I am not sure the subject of my post adequately describes the problem I
am trying to solve, so I think a specific example would be helpful.
Let's say there are XML descriptions of products like this one:
<!-- File: Products.xml -->
...
<Product id="p1">
<Title>....</Title>
...
<PricingInfo>
<RegularPrice>100</RegularPrice>
<Discount>25</Discount>
...
</PricingInfo>
...
<ShippingInfo>
<Cost>9.95</Cost>
<MaxDelay>1 business day</MaxDelay>
...
</ShippingInfo>
...
</Product>
The key thing here is that the schema of <Product> is not "flat" - it
contains elements with subelements, which may also have subelements,
and so on...
Now, let's say that I want to have an XML file that describes some sort
of an HTML page template which, in particular, refers to certain
attributes of <Product>s. Something along these lines:
<!-- File: PageTemplate.xml -->
...
<section>General</section>
<p>Title: <ProductProperty rxpath="Title"/></p>
<section>Shipping Info</section>
<p>Cost: <ProductProperty rxpath="ShippingInfo/Cost"/></p>
<p>Delay: <ProductProperty rxpath="ShippingInfo/Delay"/></p>
...
Finally, in an XSL file, whose templates are supposed to be applied to
PageTemplate.xml, I would like to write something like this:
<!-- File: ProductPage.xsl -->
...
<xs:template match="ProductProperty">
<!-- The parameter contains a nodeset from Products.xml -->
<!-- Or there could be a variable with the same contents... -->
<xsaram name="nsProduct" tunnel="yes"/>
<!-- And below is where the fun begins... -->
<xs:apply-templates
select="$nsProduct/*[name()=current()/@rxpath]"/>
</xs:template>
The problem is: I do not know what could I specify the @select
attribute of the <xs:apply-templates> element to retrieve exactly the
sub-nodeset of <Product> element defined by the @rxpath attribute of
the <ProductProperty> element.
The expression I wrote above -- $nsProduct/*[name()=current()/@rxpath]
-- works fine for @rxpaths that specify direct children of the
<Product> element (like "Title"), but obviously does not work for any
ancestor elements (like "ShippingInfo/Cost"). So I guess I am looking
for a way to dynamically obtain a sub-nodeset of a specified "origin
nodeset" (in my example, it is defined by $nsProduct) using specified
"subpath" inside that nodeset.
In some sense, the problem is similar to what XForms are trying to
achieve: provide XML description of a data model, XML description of a
view of that data model, and bindings between view elements and data
model elements. In my case, "bindings" are supposed to be very
simplistic - just plain relative XPath expressions...
If anyone knows the trick that could let me do what I want (or
something really close to what I want) using XSLT 2.0 and XPath 2.0,
please advise. In fact, any comments would be appreciated.
Thank you,
Yarik.
I am not sure the subject of my post adequately describes the problem I
am trying to solve, so I think a specific example would be helpful.
Let's say there are XML descriptions of products like this one:
<!-- File: Products.xml -->
...
<Product id="p1">
<Title>....</Title>
...
<PricingInfo>
<RegularPrice>100</RegularPrice>
<Discount>25</Discount>
...
</PricingInfo>
...
<ShippingInfo>
<Cost>9.95</Cost>
<MaxDelay>1 business day</MaxDelay>
...
</ShippingInfo>
...
</Product>
The key thing here is that the schema of <Product> is not "flat" - it
contains elements with subelements, which may also have subelements,
and so on...
Now, let's say that I want to have an XML file that describes some sort
of an HTML page template which, in particular, refers to certain
attributes of <Product>s. Something along these lines:
<!-- File: PageTemplate.xml -->
...
<section>General</section>
<p>Title: <ProductProperty rxpath="Title"/></p>
<section>Shipping Info</section>
<p>Cost: <ProductProperty rxpath="ShippingInfo/Cost"/></p>
<p>Delay: <ProductProperty rxpath="ShippingInfo/Delay"/></p>
...
Finally, in an XSL file, whose templates are supposed to be applied to
PageTemplate.xml, I would like to write something like this:
<!-- File: ProductPage.xsl -->
...
<xs:template match="ProductProperty">
<!-- The parameter contains a nodeset from Products.xml -->
<!-- Or there could be a variable with the same contents... -->
<xsaram name="nsProduct" tunnel="yes"/>
<!-- And below is where the fun begins... -->
<xs:apply-templates
select="$nsProduct/*[name()=current()/@rxpath]"/>
</xs:template>
The problem is: I do not know what could I specify the @select
attribute of the <xs:apply-templates> element to retrieve exactly the
sub-nodeset of <Product> element defined by the @rxpath attribute of
the <ProductProperty> element.
The expression I wrote above -- $nsProduct/*[name()=current()/@rxpath]
-- works fine for @rxpaths that specify direct children of the
<Product> element (like "Title"), but obviously does not work for any
ancestor elements (like "ShippingInfo/Cost"). So I guess I am looking
for a way to dynamically obtain a sub-nodeset of a specified "origin
nodeset" (in my example, it is defined by $nsProduct) using specified
"subpath" inside that nodeset.
In some sense, the problem is similar to what XForms are trying to
achieve: provide XML description of a data model, XML description of a
view of that data model, and bindings between view elements and data
model elements. In my case, "bindings" are supposed to be very
simplistic - just plain relative XPath expressions...
If anyone knows the trick that could let me do what I want (or
something really close to what I want) using XSLT 2.0 and XPath 2.0,
please advise. In fact, any comments would be appreciated.
Thank you,
Yarik.