Re: Postgresql 8.4, XPath and name() function

From: Craig Ringer <craig(at)postnewspapers(dot)com(dot)au>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: Postgresql 8.4, XPath and name() function
Date: 2010-07-14 01:08:14
Message-ID: 4C3D0DFE.7090408@postnewspapers.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On 14/07/2010 12:09 AM, Tim Landscheidt wrote:
> ced45<cedric(dot)duprez(at)ifn(dot)fr> wrote:
>
>> I have trouble using XPath name() function in a XML field.
>> For example, when I execute the following query :
>
>> SELECT XPATH('name(/*)', XMLPARSE(DOCUMENT '<unit>value</unit>'))

It seems very odd that that returns an empty set. I'd expect that it
should return "unit" if the xpath is being evaluated as an expression,
or fail to compile if the xpath is being used as a selector.

In XSLT you couldn't use "name(/*)" as a selector in template match
expression.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="name(/*)">
<xsl:element name="was-in-unit">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

$ xsltproc demo.xsl demo.xml
error
xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type
compilation error: file demo.xsl line 5 element template
xsltCompilePattern : failed to compile 'name(/*)'

... but if "name(/*)" was evaluated as a value-expression it'd return
"unit".

PostgreSQL's docs say:

"The function xpath evaluates the XPath expression xpath against the XML
value xml. It returns an array of XML values corresponding to the node
set produced by the XPath expression."

http://developer.postgresql.org/pgdocs/postgres/functions-xml.html

and as the above xpath expression **should** return the node-set of a
single text node with the value "unit", I'm a bit puzzled as to how Pg
is getting an empty array.

>> I would like to get "unit", but I just get an empty array ({}).
>> How can I get "unit" ?
>
> AFAIK, this is not related to PostgreSQL, but inherent to
> XPath in that it returns elements from the document that
> fulfill the XPath expression *unchanged*.

My (poor) understanding is that XPath can be used as an expression
language and as a selector specifier language. You can observe this in
XSLT, where

<xsl:template match="some-xpath"/>

uses XPath as a selector of elements, and:

<xsl:value-of select="some-xpath"/>

uses XPath as an expression language, returning the output of a given
XPath expression or function not just the "matched"/"not matched" status.

I found this very confusing myself when learning XSLT, and it's possible
I'm still misunderstanding it somewhat, but it's clear that XPath can be
used in more than one way.

It seems that PostgreSQL is using it as a selector/specifier - ie "what
matches this xpath". The OP wants to use it as an expression language,
to get the result of the xpath expression not just the element it matches.

In the first use, as just a match expression, you'd see it applied like
this:

demo.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/unit"> <!-- selector -->
<xsl:element name="was-in-unit">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

$ xsltproc demo.xsl demo.xml
<?xml version="1.0"?>
<was-in-unit>value</was-in-unit>

In the second use, like this:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:value-of select="name(/*)"/> <!-- expression -->
</xsl:template>
</xsl:stylesheet>

$ xsltproc demo.xsl demo.xml
<?xml version="1.0"?>
unit

--
Craig Ringer

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Craig Ringer 2010-07-14 03:10:37 Re: PG_DUMP very slow because of STDOUT ??
Previous Message Craig Ringer 2010-07-14 00:47:35 Re: Planner features, discussion