FW: A Modest Proposal for the Re-inflation of XPath to an XML Syn tax

Sirs - 
	I am forwarding to you a message I posted recently to xsl-list.
Please consider it a suggestion for inclusion in the XPath specification. I
appreciate that XPath and XSLT are in last call, however, my suggestion
doesn't change the power of the XPath language, only it's expression. I
understand the time pressure you are under, so I don't expect direct
feedback.
Thank you,
David vun Kannon

-----Original Message-----
From: Vun Kannon, David [mailto:dvunkannon@kpmg.com]
Sent: Wednesday, August 18, 1999 11:13 PM
To: xsl-list@mulberrytech.com
Subject: A Modest Proposal for the Re-inflation of XPath to an XML
Syntax


A Modest Proposal for the Re-inflation of XPath to an XML Syntax

	The language jointly used by Xpointer and XSLT, XPath, currently has
a concrete reference syntax that is not the same as XML. This is perceived
as a benefit because the syntax in use can be stored in the string
representation of an attribute value. However, not using the instance syntax
of XML does introduce some difficulties. All of the armamentarium and
impedimenta of the XML arsenal, especially pointing, linking, the DOM and
transformation, cannot be brought to bear on XPath expressions because they
are not in XML syntax. The work of the XSchema WG is cast in XML at least in
small part for these reasons.
	Assuming that XPath expressions will always appear as attribute
values makes it harder to treat them as first class objects. They are harder
to name, therefore harder to reuse. They are harder to document, since
comments cannot be interspersed within the expression. They are harder to
address, because the apparatus necessary to locate and count their parts is
not the same as XML's and cannot be assumed to be available. They are harder
to parameterise therefore, and therefore doubly hard to reuse.
	It may seem odd to harp on the reusability of XPath expressions. I
believe that reusability is important. Reusability arises when considering
the matter of idiom and "best practice". "not(position()=last())" is an
important idiom in the creation of comma separated lists in text.
"ancestor-or-self::*[@$inherit][1]/@$inherit" is a (parameterised) idiom for
obtaining the right value for an attribute that is inherited and attachable
anywhere in the node tree (overridable). 
	Other idioms are specific to the task, but appear multiple times in
a document or stylesheet. Because idioms are important, are often best
practices, they should be coded once and in a well documented way, such that
new staff can be educated in their use, and changes to the idiom don't have
to be hunted down in every instance document. In a similar manner,
relational databases took a step forward in ease of use when they allowed
stored procedures and triggers, which allowed SQL statements to be named,
reused, and stored in the database, not in the source code of the programs
that used them.

	A document using inflated XPath expressions would look like this:
<template xpi:inflated-match="ID001">
	<apply-templates/>
</template>
<xpi:path-expression id="ID001">
	<root/>
</xpi:path-expression>

	instead of this:
<template match="/">
	<apply-templates/>
</template>

	where "xpi" is the "XPath Inflated" namespace, suitably defined.
However, the URIs do not have to be anything as ugly and anti-mnemonic as
ID001. They should more properly be "CSV" or "inherit?attr=color".

	While the up-translation of XPath to an XML syntax  can be
undertaken by individuals in an ad hoc way, and suited only to their own
purposes, I believe that it would benefit the XML-using community at large
if there was an officially sanctioned way to describe XPath expressions in
an XML instance syntax. The use of such a syntax would be optional, just as
the use of the full or abbreviated syntax is a matter of choice.
	Below I present a sketch of such a syntax by recasting each of the
examples from the latest XPath WD in a manner of my own devising. I've tried
to be consistent, but please do not let the failings of this attempt make
you think less of the concept. I look forward to a discussion of the issues
raised, in this and other forums as appropriate.
Yours,
David vun Kannon


child::para selects the para element children of the context node
<child>para</child>

child::* selects all element children of the context node
<child><element/></child>

child::text() selects all text node children of the context node
<child><text/></child>

child::node() selects all the children of the context node, whatever their
node type
<child><node/></child>

attribute::name selects the name attribute of the context node
<attribute>name</attribute>

attribute::* selects all the attributes of the context node
<attribute><all/></attribute>

descendant::para selects the para element descendants of the context node
<descendant>para</descendant>

ancestor::div selects all div ancestors of the context node
<ancestor>div</ancestor>

ancestor-or-self::div selects the div ancestors of the context node and, if
the context node is a div element, the context node as well
<ancestor-or-self>div</ancestor-or-self>

descendant-or-self::para selects the para element descendants of the context
node and, if the context node is a para element, the context node as well
<descendant-or-self>para</descendant-or-self>

self::para selects the context node if it is a para element, and otherwise
selects nothing
<self>para</self>

child::chapter/descendant::para selects the para element descendants of the
chapter element children of the context node
<child>
	chapter
	<descendant>
		para
	</descendant>
</child>

child::*/child::para selects all para grandchildren of the context node
<child>
	<element/>
	<child>
		para
	</child>
</child>

/ selects the document root (which is always the parent of the document
element)
<root/>

/descendant::para selects all the para elements in the same document as the
context node
<root>
	<descendant>
		para
	</descendant>
<root>

/descendant::olist/child::item selects all the item elements in the same
document as the context node that have an olist parent
<root>
	<descendant>
		olist
		<child>
			item
		</child>
	</descendant>
</root>

child::para[position()=1] selects the first para child of the context node
<child>
	para
	<predicate>
		<equal>
			<position/>
			<number>1</number>
		</equal>
	</predicate>
</child>

child::para[position()=last()] selects the last para child of the context
node
<child>
	para
	<predicate>
		<equal>
			<position/>
			<last/>
		</equal>
	</predicate>
</child>

child::para[position()=last()-1] selects the last but one para child of the
context node
<child>
	para
	<predicate>
		<equal>
			<position/>
			<minus>
				<last/>
				<number>1</number>
			</minus>
		</equal>
	</predicate>
</child>

child::para[position()>1] selects all the para children of the context node
other than the first para child of the context node
<child>
	para
	<predicate>
		<greater-than>
			<position/>
			<number>1</number>
		</greater-than>
	</predicate>
</child>

following-sibling::chapter[position()=1] selects the next chapter sibling of
the context node
<following-sibling>
	chapter
	<predicate>
		<equal>
			<position/>
			<number>1</number>
		</equal>
	</predicate>
</following-sibling>

preceding-sibling::chapter[position()=1] selects the previous chapter
sibling of the context node
<preceding-sibling>
	chapter
	<predicate>
		<equal>
			<position/>
			<number>1</number>
		</equal>
	</predicate>
</preceding-sibling>

/descendant::figure[position()=42] selects the forty-second figure element
in the document
<root>
<descendant>
	figure
	<predicate>
		<equal>
			<position/>
			<number>42</number>
		</equal>
	</predicate>
</descendant>
</root>

/child::doc/child::chapter[position()=5]/child::section[position()=2]
selects the second section of the fifth chapter of the doc document element
<root>
	<child>
		doc
		<child>
			chapter
			<predicate>
				<equal>
					<position/>
					<number>5</number>
				</equal>
			</predicate>
			<child>
				section
				<predicate>
					<equal>
						<position/>
						<number>2</number>
					</equal>
				</predicate>
			</child>
		</child>
	</child>
</root>

child::para[attribute::type="warning"] selects all para children of the
context node that have a type attribute with value warning 
<child>
	para
	<predicate>
		<equal>
			<attribute>type</attribute>
			<string>warning</string>
		</equal>
	</predicate>
</child>

child::para[attribute::type='warning'][position()=5] selects the fifth para
child of the context node that has a type attribute with value warning 
<child>
	para
	<predicate>
		<equal>
			<attribute>type</attribute>
			<string>warning</string>
		</equal>
	</predicate>
	<predicate>
		<equal>
			<position/>
			<number>5</number>
		</equal>
	</predicate>
</child>

child::para[position()=5][attribute::type="warning"] selects the fifth para
child of the context node if that child has a type attribute with value
warning 
<child>
	para
	<predicate>
		<equal>
			<position/>
			<number>5</number>
		</equal>
	</predicate>
	<predicate>
		<equal>
			<attribute>type</attribute>
			<string>warning</string>
		</equal>
	</predicate>
</child>

child::chapter[child::title='Introduction'] selects the chapter children of
the context node that have one or more title children with string-value
equal to Introduction 
<child>
	chapter
	<predicate>
		<equal>
			<child>title</child>
			<string>warning</string>
		</equal>
	</predicate>
</child>

child::chapter[child::title] selects the chapter children of the context
node that have one or more title children
<child>
	chapter
	<predicate>
		<child>title</child>
	</predicate>
</child>

child::*[self::chapter or self::appendix] selects the chapter and appendix
children of the context node
<child>
	<element/>
	<predicate>
		<or>
			<self>title</self>
			<self>appendix</self>
		</or>
	</predicate>
</child>

child::*[self::chapter or self::appendix][position()=last()] selects the
last chapter or appendix child of the context node
<child>
	<element/>
	<predicate>
		<or>
			<self>title</self>
			<self>appendix</self>
		</or>
	</predicate>
	<predicate>
		<equal>
			<position/>
			<last/>
		</equal>
	</predicate>
</child>

child::div/child::para selects the para element children of the div element
children of the context node, or, in other words, the para element
grandchildren that have div parents
<child>
	div
	<child>
		para
	</child>
</child>

child::para[position()=1], child is the name of the axis, para is the node
test and [position()=1] is a predicate
<child>
	para
	<predicate>
		<equal>
			<position/>
			<number>1</number>
		</equal>
	</predicate>
</child>

para selects the para element children of the context node
<child>para</child>

* selects all element children of the context node
<child><element/><child>

text() selects all text node children of the context node
<child><text/></child>

@name selects the name attribute of the context node
<attribute>name</attribute>

@* selects all the attributes of the context node
<attribute><all/></attribute>

para[1] selects the first para child of the context node
<child>
	para
	<predicate>
		<equal>
			<position>
			<number>1</number>
		</equal>
	</predicate>
</child>

para[last()] selects the last para child of the context node
<child>
	para
	<predicate>
		<equal>
			<position>
			<last/>
		</equal>
	</predicate>
</child>

*/para selects all para grandchildren of the context node
<child>
	<element/>
	<child>
		para
	</child>
</child>

/doc/chapter[5]/section[2] selects the second section of the fifth chapter
of the doc 
<root>
	<child>
		doc
		<child>
			chapter
			<predicate>
				<equal>
					<position/>
					<number>5</number>
				</equal>
			</predicate>
			<child>
				section
				<predicate>
					<equal>
						<position/>
						<number>2</number>
					</equal>
				</predicate>
			</child>
		</child>
	</child>
</root>

chapter//para selects the para element descendants of the chapter element
children of the context node
<child>
	chapter
	<descendant-or-self>
		<node/>
		<child>
			para
		</child>
	</descendant-or-self>
</child>

//para selects all the para descendants of the document root and thus
selects all para elements in the same document as the context node
<root>
	<descendant-or-self>
		<node/>
		<child>
			para
		</child>
	</descendant-or-self>
</root>

//olist/item selects all the item elements in the same document as the
context node that have an olist parent
<root>
	<descendant-or-self>
		<node/>
		<child>
			olist
			<child>
				item
			</child>
		</child>
	</descendant-or-self>
</root>

. selects the context node
<self><node/></self>

.//para selects the para element descendants of the context node
<self>
	<node/>
	<descendant-or-self>
		<node/>
		<child>
			para
		</child>
	</descendant-or-self>
</self>

.. selects the parent of the context node
<parent><node/><parent/>

../@lang selects the lang attribute of the parent of the context node
<parent>
	<node/>
	<attribute>
		lang
	</attribute>
</parent>

para[@type="warning"] selects all para children of the context node that
have a type attribute with value warning 
<child>
	para
	<predicate>
		<equal>
			<attribute>type</attribute>
			<string>warning</string>
		</equal>
	</predicate>
</child>

para[@type="warning"][5] selects the fifth para child of the context node
that has a type attribute with value warning 
<child>
	para
	<predicate>
		<equal>
			<attribute>type</attribute>
			<string>warning</string>
		</equal>
	</predicate>
	<predicate>
		<equal>
			<position/>
			<number>5</number>
		</equal>
	</predicate>
</child>

para[5][@type="warning"] selects the fifth para child of the context node if
that child has a type attribute with value warning 
<child>
	para
	<predicate>
		<equal>
			<position/>
			<number>5</number>
		</equal>
	</predicate>
	<predicate>
		<equal>
			<attribute>type</attribute>
			<string>warning</string>
		</equal>
	</predicate>
</child>

chapter[title="Introduction"] selects the chapter children of the context
node that have one or more title children with string-value equal to
Introduction 
<child>
	chapter
	<predicate>
		<equal>
			<child>title</child>
			<string>Introduction</string>
		</equal>
	</predicate>
</child>

chapter[title] selects the chapter children of the context node that have
one or more title children
<child>
	chapter
	<predicate>
		<child>title</child>
	</predicate>
</child>

employee[@secretary and @assistant] selects all the employee children of the
context node that have both a secretary attribute and an assistant attribute
<child>
	employee
	<predicate>
		<and>
			<attribute>secretary</attribute>
			<attribute>assistant</atttribute>
		</and>
	</predicate>
</child>




****************************************************************************
*
The information in this email is confidential and may be legally privileged.
It is intended solely for the addressee. Access to this email by anyone else
is unauthorized. 

If you are not the intended recipient, any disclosure, copying, distribution
or any action taken or omitted to be taken in reliance on it, is prohibited
and may be unlawful. When addressed to our clients any opinions or advice
contained in this email are subject to the terms and conditions expressed in
the governing KPMG client engagement letter.         
****************************************************************************
*


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
*****************************************************************************
The information in this email is confidential and may be legally privileged.
It is intended solely for the addressee. Access to this email by anyone else
is unauthorized. 

If you are not the intended recipient, any disclosure, copying, distribution
or any action taken or omitted to be taken in reliance on it, is prohibited
and may be unlawful. When addressed to our clients any opinions or advice
contained in this email are subject to the terms and conditions expressed in
the governing KPMG client engagement letter.         
*****************************************************************************

Received on Friday, 20 August 1999 14:37:38 UTC