Postgresql 8.4, XPath and name() function

Lists: pgsql-general
From: ced45 <cedric(dot)duprez(at)ifn(dot)fr>
To: pgsql-general(at)postgresql(dot)org
Subject: Postgresql 8.4, XPath and name() function
Date: 2010-07-13 08:03:23
Message-ID: 29147655.post@talk.nabble.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general


Hi List,

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>'))

I would like to get "unit", but I just get an empty array ({}).
How can I get "unit" ?

Thanks in advance,

Cedric
--
View this message in context: http://old.nabble.com/Postgresql-8.4%2C-XPath-and-name%28%29-function-tp29147655p29147655.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.


From: Thom Brown <thombrown(at)gmail(dot)com>
To: ced45 <cedric(dot)duprez(at)ifn(dot)fr>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: Postgresql 8.4, XPath and name() function
Date: 2010-07-13 08:36:42
Message-ID: AANLkTinpGhcOJ6_W1PbuWknQ0xcK1Ycp9apsSCRM0cfJ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On 13 July 2010 09:03, ced45 <cedric(dot)duprez(at)ifn(dot)fr> wrote:
>
> Hi List,
>
> 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>'))
>
> I would like to get "unit", but I just get an empty array ({}).
> How can I get "unit" ?
>
eneral(at)postgresql(dot)org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

Have you tried:

SELECT XPATH('fn:name(/*)', XMLPARSE(DOCUMENT '<unit>value</unit>'));

Thom


From: ced45 <cedric(dot)duprez(at)ifn(dot)fr>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: Postgresql 8.4, XPath and name() function
Date: 2010-07-13 08:44:00
Message-ID: 29148011.post@talk.nabble.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Thom Brown wrote:
>
> Have you tried:
>
> SELECT XPATH('fn:name(/*)', XMLPARSE(DOCUMENT '<unit>value</unit>'));
>
> Thom
>
>
Thanks for your help, but it gives the whole element and not only the markup
name.

Cedric
--
View this message in context: http://old.nabble.com/Postgresql-8.4%2C-XPath-and-name%28%29-function-tp29147655p29148011.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.


From: Tim Landscheidt <tim(at)tim-landscheidt(dot)de>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: Postgresql 8.4, XPath and name() function
Date: 2010-07-13 16:09:27
Message-ID: m3zkxvgy88.fsf@passepartout.tim-landscheidt.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

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>'))

> 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*.

So you will probably have to tackle your problem from an-
other angle.

Tim


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
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


From: Tim Landscheidt <tim(at)tim-landscheidt(dot)de>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: Postgresql 8.4, XPath and name() function
Date: 2010-07-14 16:06:04
Message-ID: m3oceagiab.fsf@passepartout.tim-landscheidt.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Craig Ringer <craig(at)postnewspapers(dot)com(dot)au> wrote:

> [...]
>>> 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.
> [...]

Okay, that's maybe due to my XML socialization: An XPath ex-
pression to me has always been something you use in
"xsl:template" and "xmllint --shell", as in "xsl:value-of" &
Co. you have also access to other functions. It's even in
the specification :-):

| [...] The primary purpose
| of XPath is to address parts of an XML [XML] document. [...]

(from: <URI:http://www.w3.org/TR/xpath/>)

Tim


From: Merlin Moncure <mmoncure(at)gmail(dot)com>
To: ced45 <cedric(dot)duprez(at)ifn(dot)fr>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: Postgresql 8.4, XPath and name() function
Date: 2010-07-14 17:30:16
Message-ID: AANLkTiktGlmIivdLyYltUwPjMquz7VLgwKoovviBNR2o@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Tue, Jul 13, 2010 at 4:03 AM, ced45 <cedric(dot)duprez(at)ifn(dot)fr> wrote:
>
> Hi List,
>
> 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>'))
>
> I would like to get "unit", but I just get an empty array ({}).
> How can I get "unit" ?

postgres is slightly broken in this regard. here is some discussions
and a (might not work anymore) patch to fix the behavior if you're
feeling adventurous...

http://www.mail-archive.com/pgsql-hackers(at)postgresql(dot)org/msg143339.html

here is a 'works for my cases but probably not all of yours' regex
solution that I use sometimes:
create or replace function xnode(_xml xml) returns text as
$$
select substring($1::text from '^<([[:alnum:]]+).*>');
$$ language sql immutable;

merlin