Xpath query to return "NULL" values?

Discussion in 'XML' started by Mario Splivalo, Jun 5, 2009.

  1. Here is my XML document:

    <a>
    <b>1</b>
    <b>2</b>
    <b></b>
    <b>3</b>
    </a>

    When I execute this XPath query against it: /a/b/text()

    I get only 1, 2 and 3:

    mario@mike:~$ echo "<a><b>1</b><b>2</b><b></b><b>3</b></a>" | xpath -e '/a/b/@id'
    Found 3 nodes in stdin:
    -- NODE --
    1
    -- NODE --
    2
    -- NODE --
    3
    mario@mike:~$

    Is there a way to extract that NULL-valued node?

    Mike
    --
    "I can do it quick. I can do it cheap. I can do it well. Pick any two."

    Mario Splivalo
     
    Mario Splivalo, Jun 5, 2009
    #1
    1. Advertising

  2. Mario Splivalo wrote:
    > Here is my XML document:
    >
    > <a>
    > <b>1</b>
    > <b>2</b>
    > <b></b>
    > <b>3</b>
    > </a>
    >
    > When I execute this XPath query against it: /a/b/text()
    >
    > I get only 1, 2 and 3:
    >
    > mario@mike:~$ echo "<a><b>1</b><b>2</b><b></b><b>3</b></a>" | xpath -e '/a/b/@id'


    Why /a/b/@id? There is no 'id' attribute in there at all.


    > Is there a way to extract that NULL-valued node?


    There is an empty 'b' element in there. If you want to select all 'b'
    elements then use the XPath
    /a/b
    if you only want the empty 'b' elements then use
    /a/b[not(node())]


    --

    Martin Honnen
    http://msmvps.com/blogs/martin_honnen/
     
    Martin Honnen, Jun 5, 2009
    #2
    1. Advertising

  3. Mario Splivalo wrote:
    > Here is my XML document:
    >
    > <a>
    > <b>1</b>
    > <b>2</b>
    > <b></b>
    > <b>3</b>
    > </a>
    >
    > When I execute this XPath query against it: /a/b/text()
    >
    > I get only 1, 2 and 3:
    >
    > mario@mike:~$ echo "<a><b>1</b><b>2</b><b></b><b>3</b></a>" | xpath -e '/a/b/@id'
    > Found 3 nodes in stdin:
    > -- NODE --
    > 1
    > -- NODE --
    > 2
    > -- NODE --
    > 3
    > mario@mike:~$
    >
    > Is there a way to extract that NULL-valued node?
    >
    > Mike


    xpath doesn't have a NULL value, and text nodes never have an empty
    string as value. the third b has no child node at all.
    It's actually rather rare to use text() in xpath, normally you'd just
    select the b nodes
    the xpath /a/b will select 4 b nodes with string values
    "1" "2" "" "3"
    In xpath 1 you can only have a node set so teh set of b nodes is the
    nearest you can get to this.
    In xpath2 you could return the sequence of string values directly as
    /a/b/string(.)

    David


    --
    http://dpcarlisle.blogspot.com
     
    David Carlisle, Jun 5, 2009
    #3
  4. On 2009-06-05, Martin Honnen <> wrote:
    > Mario Splivalo wrote:
    >> Here is my XML document:
    >>
    >> <a>
    >> <b>1</b>
    >> <b>2</b>
    >> <b></b>
    >> <b>3</b>
    >> </a>
    >>
    >> When I execute this XPath query against it: /a/b/text()
    >>
    >> I get only 1, 2 and 3:
    >>
    >> mario@mike:~$ echo "<a><b>1</b><b>2</b><b></b><b>3</b></a>" | xpath -e '/a/b/@id'

    >
    > Why /a/b/@id? There is no 'id' attribute in there at all.


    A typo, I'd say :) This is the correct Xpath query:

    .... | xpath -e '/a/b/text()'

    >
    >
    >> Is there a way to extract that NULL-valued node?

    >
    > There is an empty 'b' element in there. If you want to select all 'b'
    > elements then use the XPath
    > /a/b


    The 'trouble' is that I get XML portions, and I wanted 'clean' strings. I
    guess I could do another XPath query on return values, and then easily see
    wich ones are 'empty'.

    > if you only want the empty 'b' elements then use
    > /a/b[not(node())]


    That does me no good because I need to know on (in?) which position the
    empty element is. My actuall XML (shoul've written that in the OP) looks
    like this:

    <itemList>
    <item fieldName="name">Mario</item>
    <item fieldName="age">29</item>
    <item fieldName="height"></item>
    </itemList>

    What I'm trying to get is a rowset or table, since I'm doing this from
    postgres. So, my table would look like this:

    fieldName fieldValue
    name Mario
    age 29
    height NULL

    The idea was to have two XPath queries on the original XML. First one
    ('/itemList/item/@fieldName') would extract all the attributes, and second
    one would extract all the 'values' ('/itemList/item/text()'). Now I guess
    I'll have to extract the nodes, as you've suggested, and then for each node
    chech if it's empty or not.

    Mike
    --
    "I can do it quick. I can do it cheap. I can do it well. Pick any two."

    Mario Splivalo
     
    Mario Splivalo, Jun 6, 2009
    #4
  5. Mario Splivalo wrote:

    > <itemList>
    > <item fieldName="name">Mario</item>
    > <item fieldName="age">29</item>
    > <item fieldName="height"></item>
    > </itemList>
    >
    > What I'm trying to get is a rowset or table, since I'm doing this from
    > postgres. So, my table would look like this:
    >
    > fieldName fieldValue
    > name Mario
    > age 29
    > height NULL
    >
    > The idea was to have two XPath queries on the original XML. First one
    > ('/itemList/item/@fieldName') would extract all the attributes, and second
    > one would extract all the 'values' ('/itemList/item/text()'). Now I guess
    > I'll have to extract the nodes, as you've suggested, and then for each node
    > chech if it's empty or not.


    Are you using XPath inside of XSLT? There is no need to use foo/text()
    to get the string value of a 'foo' element, an element does have a
    string value of its own for instance with XSLT
    <xsl:value-of select="foo"/>
    would suffice. If you are using an XPath API then check how it allows
    you to extract the string value of a node.


    --

    Martin Honnen
    http://msmvps.com/blogs/martin_honnen/
     
    Martin Honnen, Jun 6, 2009
    #5
  6. On 2009-06-06, Martin Honnen <> wrote:
    > Mario Splivalo wrote:
    >
    >> <itemList>
    >> <item fieldName="name">Mario</item>
    >> <item fieldName="age">29</item>
    >> <item fieldName="height"></item>
    >> </itemList>
    >>
    >> What I'm trying to get is a rowset or table, since I'm doing this from
    >> postgres. So, my table would look like this:
    >>
    >> fieldName fieldValue
    >> name Mario
    >> age 29
    >> height NULL
    >>
    >> The idea was to have two XPath queries on the original XML. First one
    >> ('/itemList/item/@fieldName') would extract all the attributes, and second
    >> one would extract all the 'values' ('/itemList/item/text()'). Now I guess
    >> I'll have to extract the nodes, as you've suggested, and then for each node
    >> chech if it's empty or not.

    >
    > Are you using XPath inside of XSLT? There is no need to use foo/text()
    > to get the string value of a 'foo' element, an element does have a
    > string value of its own for instance with XSLT
    > <xsl:value-of select="foo"/>
    > would suffice. If you are using an XPath API then check how it allows
    > you to extract the string value of a node.


    Nope, I'm using it inside postgresql. Postgresql has rudimentary XML support
    (http://www.postgresql.org/docs/8.3/interactive/functions-xml.html#FUNCTIONS-XML-PROCESSING)
    there is a XPath function which returns onedimensional array of type xml[]
    (xml type, in postgres, is varchar/text with added support for xml
    validation). Function accept xpath query and xml document, I'm clueless how
    to extract string value of a node. It's based on libxml2, so it should be
    able to do so, but, I guess i'm stuck:

    postgres=# select xpath('/a/b', '<a><b>1</b><b></b></a>');
    xpath
    -----------------
    {<b>1</b>,<b/>}
    (1 row)

    So, I have an array where each element is XML document. I could run an xpath
    query ('/b') on each of those elements and like that find out which ones are
    empty.

    Mike
    --
    "I can do it quick. I can do it cheap. I can do it well. Pick any two."

    Mario Splivalo
     
    Mario Splivalo, Jun 6, 2009
    #6
  7. Mario Splivalo wrote:

    > Nope, I'm using it inside postgresql. Postgresql has rudimentary XML support
    > (http://www.postgresql.org/docs/8.3/interactive/functions-xml.html#FUNCTIONS-XML-PROCESSING)
    > there is a XPath function which returns onedimensional array of type xml[]
    > (xml type, in postgres, is varchar/text with added support for xml
    > validation). Function accept xpath query and xml document, I'm clueless how
    > to extract string value of a node.


    I don't know Postgresql at all so I can't help with that. You might want
    to check whether there are Postgresql specific forums where you have
    better chances of finding others with experience and knowledge of that
    particular API.

    --

    Martin Honnen
    http://msmvps.com/blogs/martin_honnen/
     
    Martin Honnen, Jun 6, 2009
    #7
  8. Mario Splivalo wrote:
    > <a>
    > <b>1</b>
    > <b>2</b>
    > <b></b>
    > <b>3</b>
    > </a>
    >
    > When I execute this XPath query against it: /a/b/text()
    > I get only 1, 2 and 3:


    That is correct. In the XML data model, an empty element has no children
    at all, so /a/b/text() or indeed /a/b/node() will skip over that entirely.

    If you want an empty string, you could rewrite this as

    /a/b/string(.)

    which returns the string value of each <b> element in turn. Since the
    string value of an element is the concatenation of its contained text
    nodes, this will yield the results you expected.
     
    Joe Kesselman, Jun 6, 2009
    #8
  9. Joe Kesselman wrote:

    > If you want an empty string, you could rewrite this as
    >
    > /a/b/string(.)
    >
    > which returns the string value of each <b> element in turn.



    But the above syntax is XPath 2.0 only.

    --

    Martin Honnen
    http://msmvps.com/blogs/martin_honnen/
     
    Martin Honnen, Jun 6, 2009
    #9
  10. Martin Honnen wrote:
    >> /a/b/string(.)
    >> which returns the string value of each <b> element in turn.

    >
    > But the above syntax is XPath 2.0 only.


    Sorry; I'm spending too much time moving between 1.0 and 2.0 right now
    and got confused.

    In that case... The right answer may be to separate this into separate
    operations -- issue an XPath to find the b's, then explicitly loop over
    those and retrieve/process the node values.
     
    Joe Kesselman, Jun 7, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kathy Burke
    Replies:
    0
    Views:
    713
    Kathy Burke
    Aug 3, 2003
  2. Replies:
    5
    Views:
    27,598
    Mike Schilling
    Mar 29, 2006
  3. David Gordon

    xpath query query

    David Gordon, May 18, 2005, in forum: XML
    Replies:
    2
    Views:
    833
    David Gordon
    May 18, 2005
  4. Carl
    Replies:
    21
    Views:
    1,029
    Patricia Shanahan
    Aug 24, 2006
  5. Francois Grieu
    Replies:
    14
    Views:
    861
    Micah Cowan
    Mar 7, 2008
Loading...

Share This Page