I had a doubt about this concept, and asked following question on xsl-list.
Supposing I write the following XPath expressions,
1) X[c1][c2] or specifying generically, X[c1][c2][]...[cn]
2) X[c1 and c2] or specifying generically, X[c1 and c2 ... and cn]
where c1, c2 etc. are boolean expressions.
are the two forms (1 & 2) above exactly equivalent (i.e., will they return the same nodeset/sequence)? I think yes ... but just wanted to confirm with the list.
if 1 & 2 are exactly equivalent, then what could be the rule of thumb for using which form in certain scenarios?
There was a good discussion on the list about this, and list members shared some useful thoughts.
Below is a summary of the points we discussed on the list.
1. David Carlisle
> are the two forms (1 & 2) above exactly equivalent
No
compare
X[position()=2][position()=2]
and
[position()=2 and position()=2]
the first one is
()
the second is
X[2]
David further wrote,
context position (position()) and size (last()) do change. so basically repeated filters are equivalent to and unless any of them depend on position() or last(), including the special case of [integer] being equivalent to [position()=integer]
this last case is what makes it tricky to do a static rewrite of this.
If you have
X[... foo ..][... bar ...]
you can only rewrite that to
X[(... foo ..) and (... bar ...)]
if you know that neither expression will evaluate to a number at run time.
2. Vasu Chakkera
If that were true, then the condition
myelement[@myattribute][1] should be same as
myelement[1][@myattribute], which is not true...
The predicate order is important
in a typical "and"
[a and b] = [b and a]
3. Andrew Welch
Only / will change the context node, so I would've thought one predicate after the other is pretty much equivalent apart from cases that rely on size of the selection (which is the only thing that changes after each predicate).
Mukul: I asked a related question in continuation to this.
for real world XSLT/XPath programs, upto how many predicates can we typically see?
I haven't seen programs using 3, 4 or more predicates.
X[..][..][..][..]
I have used only one or two predicates upto now.
are excessively large number or predicates really useful? (though, the syntax allows that)
I think perhaps, for complex 'and' conditions, using multiple predicates are useful.
David shared an interesting observation about this:
He has been using some stylesheets having upto 11 predicates.
He wrote:
> are excessively large number or predicates really useful? (though, the syntax allows that)
isn't that like asking if complicated expressions are useful? they are useful if you need them, otherwise they are not.
3 or 4 predicates is totally routine but the most common reason for having larger numbers is to filter attributes
[not(@purpose='iemode')]
[not(@purpose='artifact')]
[not(@purpose='w-dimension')]
is equivalent to
[not(@purpose='iemode') and
[not(@purpose='artifact') and
[not(@purpose='w-dimension')]
but I'd almost always use the first form in XSLT 1.0 because it's easier to indent and easier to refactor, but if starting from the beginning in XSLT 2.0 I'd write it as
[not(@purpose=('iemode','artifact','w-dimension'))]
Mukul: This was a nice discussion I believe, and I have learnt few useful concepts.
Saturday, November 22, 2008
Tuesday, November 4, 2008
fn:contains -> multiple strings to compare with
An XSLT user asked following question on xsl-list:
I want to have something that does this: contains('$d/ris:organ/text()', 'Hamburg' or 'Koblenz' or 'xxx'...) ===> Compare 1 String with multpile strings.
instead of: contains('$d/ris:organ/text()','Hamburg') or contains('$d/ris:organ/text()','Koblenz')...
Andrew Welch suggested following answer:
some $x in ('Hamburg', 'Koblenz', 'xxx') satisfies
contains($d/ris:organ/text(), $x)
This uses the XPath 2.0 quantified expression, "some".
This is cool.
I was prompted to share Andrew's answer here, because I thought of a lengthy and perhaps inefficient solution for this (I feel a bit stupid, actually :) ):
I want to have something that does this: contains('$d/ris:organ/text()', 'Hamburg' or 'Koblenz' or 'xxx'...) ===> Compare 1 String with multpile strings.
instead of: contains('$d/ris:organ/text()','Hamburg') or contains('$d/ris:organ/text()','Koblenz')...
Andrew Welch suggested following answer:
some $x in ('Hamburg', 'Koblenz', 'xxx') satisfies
contains($d/ris:organ/text(), $x)
This uses the XPath 2.0 quantified expression, "some".
This is cool.
I was prompted to share Andrew's answer here, because I thought of a lengthy and perhaps inefficient solution for this (I feel a bit stupid, actually :) ):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://my-functions"
version="2.0">
<xsl:output indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:variable name="str" select="'hello xxx dd'" />
<xsl:variable name="list" select="('Hamburg','Koblenz','xxx')" />
<xsl:if test="my:contains($str, $list)">
matches
</xsl:if>
</xsl:template>
<!-- a custom 'contains' implementation -->
<xsl:function name="my:contains" as="xs:boolean">
<xsl:param name="str" as="xs:string" />
<xsl:param name="list" as="xs:string+" />
<xsl:variable name="temp" as="xs:boolean*">
<xsl:for-each select="$list">
<xsl:if test="contains($str, .)">
<xsl:sequence select="xs:boolean('true')" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:sequence select="if ($temp[1] = xs:boolean('true')) then
xs:boolean('true') else xs:boolean('false')" />
</xsl:function>
</xsl:stylesheet>
Saturday, September 27, 2008
boolean value of a RTF, in XSLT 1.0
A recent discussion on xsl-list taught me something about a feature of XSLT 1.0 language.
Let's say there is a variable reference like following, in a XSLT 1.0 code:
This will always return boolean value true.
Because, as defined in XSLT 1.0 specification,
The boolean value of a node set, with at least one node, is true. The RTF always has a root node.
It seems to me, that the function call, boolean($rtfVariable) is not very useful to applications, as it's always true.
This post applies to XSLT 1.0. I haven't cross checked what are the rules for this in XSLT 2.0.
Let's say there is a variable reference like following, in a XSLT 1.0 code:
<xsl:variable name="temp">According to the XSLT 1.0 specification, the contents of the variable temp is called a RTF (Result Tree Fragment). Now what will be the result of the following function call, boolean($temp)
<!-- anything could be here -->
</xsl:variable>
This will always return boolean value true.
Because, as defined in XSLT 1.0 specification,
The boolean value of a node set, with at least one node, is true. The RTF always has a root node.
It seems to me, that the function call, boolean($rtfVariable) is not very useful to applications, as it's always true.
This post applies to XSLT 1.0. I haven't cross checked what are the rules for this in XSLT 2.0.
Friday, September 12, 2008
Should we include <?xml version="1.0" ... in XPath data model, or DOM?
We all know that the following declaration statement appears at the beginning of most of the XML documents.
[1]
<?xml version="1.0" encoding="UTF-8"?>
But the details of the above statement is not included in a DOM tree, and neither it is part of the XPath (2.0) data model. To my opinion, this statement is used by the XML parser to initialize certain behaviors (or to enable certain properties).
I just had a weird thought, that should we not include this information as part of XPath data model, perhaps as properties of the document node; and in case of DOM, part of the DOM tree? If this declaration is not present in the XML document, then the relevant properties can be empty sequences.
The XML declaration is available in the XML infoset [2], but it's not included in a DOM, or the XPath data model.
I think, perhaps the XML declaration information is not useful to end user applications, and is only useful to the XML parser.
[2] http://www.w3.org/TR/xml-infoset/
Michael Glavassevich on xml-dev list corrected me, about DOM:
Information from the XML declaration is already stored in the DOM [3][4][5] (since DOM Level 3). Within the API the values have an effect on serialization, in-memory well-formedness checking and in-memory validation.
[3] http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-version
[4] http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-encoding
[5] http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-standalone
[1]
<?xml version="1.0" encoding="UTF-8"?>
But the details of the above statement is not included in a DOM tree, and neither it is part of the XPath (2.0) data model. To my opinion, this statement is used by the XML parser to initialize certain behaviors (or to enable certain properties).
I just had a weird thought, that should we not include this information as part of XPath data model, perhaps as properties of the document node; and in case of DOM, part of the DOM tree? If this declaration is not present in the XML document, then the relevant properties can be empty sequences.
The XML declaration is available in the XML infoset [2], but it's not included in a DOM, or the XPath data model.
I think, perhaps the XML declaration information is not useful to end user applications, and is only useful to the XML parser.
[2] http://www.w3.org/TR/xml-infoset/
Michael Glavassevich on xml-dev list corrected me, about DOM:
Information from the XML declaration is already stored in the DOM [3][4][5] (since DOM Level 3). Within the API the values have an effect on serialization, in-memory well-formedness checking and in-memory validation.
[3] http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-version
[4] http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-encoding
[5] http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Document3-standalone
Saturday, August 30, 2008
Schema aware processing with XSLT 1.0
I wrote following article, about implementing some of the Schema aware stylesheet ideas (as defined in the XSLT 2.0 spec.) using a XSLT 1.0 processor and Java extensions, and a suitable validating XML parser. A requirement from a XSLT user on this blog motivated me to work on this idea.
The article on my web site showcases just how few of the XSLT 2.0 Schema aware facilities like, validating the output tree (or even a result tree fragment) prior to serialization can be done. This covers one of the very important aspects of Schema aware XSLT 2.0 stylesheet design.
I think it's not possible to implement following Schema aware XSLT 2.0 facilities, using XSLT 1.0 and extensions alone:
1) Pass the validated XML instance tree to the XSLT processor, and the stylesheet is able to access Schema annotated XPath 2.0 data model tree. The XSLT 2.0 and XPath 2.0 languages define various Schema related instructions and expressions (for e.g., element(*, typeName) etc.), which cannot be simulated with XSLT 1.0 and extensions.
2) Since we cannot access Schema annotated XPath 2.0 data model tree in a XSLT 1.0 stylesheet, we cannot access XML Schema type names in a stylesheet, which prohibits the enhanced static typing features in XSLT stylesheets.
Using a complete Schema aware XSLT 2.0 system allows very rich static typing in XSLT stylesheets out of the box.
The article on my web site showcases just how few of the XSLT 2.0 Schema aware facilities like, validating the output tree (or even a result tree fragment) prior to serialization can be done. This covers one of the very important aspects of Schema aware XSLT 2.0 stylesheet design.
I think it's not possible to implement following Schema aware XSLT 2.0 facilities, using XSLT 1.0 and extensions alone:
1) Pass the validated XML instance tree to the XSLT processor, and the stylesheet is able to access Schema annotated XPath 2.0 data model tree. The XSLT 2.0 and XPath 2.0 languages define various Schema related instructions and expressions (for e.g., element(*, typeName) etc.), which cannot be simulated with XSLT 1.0 and extensions.
2) Since we cannot access Schema annotated XPath 2.0 data model tree in a XSLT 1.0 stylesheet, we cannot access XML Schema type names in a stylesheet, which prohibits the enhanced static typing features in XSLT stylesheets.
Using a complete Schema aware XSLT 2.0 system allows very rich static typing in XSLT stylesheets out of the box.
Friday, August 22, 2008
Nice use case for xsl:analyze-string instruction
I thought that this was interesting to share.
Recently an XSLT user discussed a problem on xsl-list, which was solved by Jeni Tennison using XSLT 1.0 long time ago.
I presented a XSLT 2.0 solution for the same problem. The 2.0 solution is lot shorter as compared to the 1.0 solution, and utilizes the XSLT 2.0 instruction, xsl:analyze-string.
The link to this thread is at, http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200808/msg00383.html.
This problem could be a nice use case for xsl:analyze-string instruction.
Recently an XSLT user discussed a problem on xsl-list, which was solved by Jeni Tennison using XSLT 1.0 long time ago.
I presented a XSLT 2.0 solution for the same problem. The 2.0 solution is lot shorter as compared to the 1.0 solution, and utilizes the XSLT 2.0 instruction, xsl:analyze-string.
The link to this thread is at, http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200808/msg00383.html.
This problem could be a nice use case for xsl:analyze-string instruction.
Thursday, August 14, 2008
Transforming tree structure from one format into another
An interesting question was asked on xsl-list,
The input XML file is something as:
Let's say that XML file has only one root node.
The output XML file would be:
A tree structure is defined in input XML, by the 'name' and 'child' attributes. The output represents a true logical tree. We should be able to cater to unlimited number of tree nodes.
We need to write a XSLT stylesheet for this.
At first thought, I imagined that this could be a tough problem. But a little bit of patience helped me to write the stylesheet for this. The solution is presented below.
At first thought, I felt that XSLT 2.0 constructs will be required to solve this problem. But the problem can be solved completely with a XSLT 1.0 stylesheet.
My belief that XSLT is a wonderful language for processing XML data, became stronger after solving this problem.
The input XML file is something as:
<Objs>
<obj name="a" child="b"/>
<obj name="b" child="c"/>
<obj name="b" child="d"/>
<obj name="c" child="e"/>
</Objs>
Let's say that XML file has only one root node.
The output XML file would be:
<Obj name="a">
<Obj name="b">
<Obj name="c">
<Obj name="e"/>
</Obj>
<Obj name="d"/>
</Obj>
</Obj>
A tree structure is defined in input XML, by the 'name' and 'child' attributes. The output represents a true logical tree. We should be able to cater to unlimited number of tree nodes.
We need to write a XSLT stylesheet for this.
At first thought, I imagined that this could be a tough problem. But a little bit of patience helped me to write the stylesheet for this. The solution is presented below.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="Objs">
<xsl:variable name="start" select="obj[not(@name = ../obj/@child)]" />
<xsl:variable name="startName" select="$start[1]/@name" />
<Obj name="{$startName}">
<xsl:for-each select="obj[(@name = $startName) and not(../obj/@name = @child)]">
<Obj name="{@child}" />
</xsl:for-each>
<xsl:call-template name="makeTree">
<xsl:with-param name="list" select="obj[@name = $start/@child]" />
</xsl:call-template>
</Obj>
</xsl:template>
<xsl:template name="makeTree">
<xsl:param name="list" />
<Obj name="{$list[1]/@name}">
<xsl:for-each select="$list">
<xsl:variable name="child" select="@child" />
<xsl:choose>
<xsl:when test="not(../obj[@name = $child])">
<Obj name="{$child}" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="makeTree">
<xsl:with-param name="list" select="../obj[@name = $child]" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</Obj>
</xsl:template>
</xsl:stylesheet>
At first thought, I felt that XSLT 2.0 constructs will be required to solve this problem. But the problem can be solved completely with a XSLT 1.0 stylesheet.
My belief that XSLT is a wonderful language for processing XML data, became stronger after solving this problem.
Subscribe to:
Posts (Atom)