xpath to get the first sibling

Discussion in 'XML' started by yawnmoth, May 22, 2009.

  1. yawnmoth

    yawnmoth Guest

    <div>
    <strong>Name: </strong> John Doe<br />
    <strong>Phone Number: </strong> 111-111-1111<br />
    <strong>Address: </strong> 111 Anywhere St.
    </div>

    Say that's my HTML. I can get the node whose value is "Name: " with
    "//strong[.='Name: ']", but how do I get " John Doe"? <http://
    www.w3schools.com/XPath/xpath_axes.asp> mentions "following-sibling"
    but neither "//strong[.='Name: ']//following-sibling" or ""//strong
    [.='Name: ']//following-sibling::*" yield any results.

    Any ideas?
    yawnmoth, May 22, 2009
    #1
    1. Advertising

  2. yawnmoth wrote:
    > <div>
    > <strong>Name: </strong> John Doe<br />
    > <strong>Phone Number: </strong> 111-111-1111<br />
    > <strong>Address: </strong> 111 Anywhere St.
    > </div>
    >
    > Say that's my HTML. I can get the node whose value is "Name: " with
    > "//strong[.='Name: ']", but how do I get " John Doe"?


    * matches the default node-type, which is usually elements. If you want
    it to match a text node, you need to say so.

    What you're looking for is:
    //strong[.='Name: ']/following-sibling::text()[1]
    .... the first text node after the <strong> whose value is "Name: '.
    (Note that if you don't specify [1], XPath will return all the following
    siblings -- which would include the <br/>, the next <strong>, and
    everything else up to the </div>.)

    Mixed content tends to be a pain to work with in XML and XSLT. You may
    want to consider structuring this more semantically, eg as a two-column
    table.
    Joe Kesselman, May 22, 2009
    #2
    1. Advertising

  3. yawnmoth

    Peter Flynn Guest

    Joe Kesselman wrote:
    > yawnmoth wrote:
    >> <div>
    >> <strong>Name: </strong> John Doe<br />
    >> <strong>Phone Number: </strong> 111-111-1111<br />
    >> <strong>Address: </strong> 111 Anywhere St.
    >> </div>
    >>
    >> Say that's my HTML. I can get the node whose value is "Name: " with
    >> "//strong[.='Name: ']", but how do I get " John Doe"?

    >
    > * matches the default node-type, which is usually elements. If you want
    > it to match a text node, you need to say so.
    >
    > What you're looking for is:
    > //strong[.='Name: ']/following-sibling::text()[1]
    > ... the first text node after the <strong> whose value is "Name: '.
    > (Note that if you don't specify [1], XPath will return all the following
    > siblings -- which would include the <br/>, the next <strong>, and
    > everything else up to the </div>.)
    >
    > Mixed content tends to be a pain to work with in XML and XSLT. You may
    > want to consider structuring this more semantically, eg as a two-column
    > table.


    Alternative: use
    <span class="label">Name:</span> <span class="name">John Doe</span>
    etc

    The abuse of <strong> emphasis is one of the unfortunate results of the
    politically-correct sanitisation of HTML undertaken by the W3C.

    Adding leading and trailing spaces to text nodes in mixed content just
    to make it look pretty is usually A Bad Idea if the document is going to
    be reprocessed.

    However, if this is someone else's document, you just have to deal with it.

    ///Peter
    --
    XML FAQ: http://xml.silmaril.ie
    Peter Flynn, May 23, 2009
    #3
  4. yawnmoth

    yawnmoth Guest

    On May 23, 10:54 am, Peter Flynn <> wrote:
    > Joe Kesselman wrote:
    > > yawnmoth wrote:

    > <snip>
    > However, if this is someone else's document, you just have to deal with it.

    That's what it is. If I was parsing my own HTML, I'd just stick with
    what I know and wouldn't have put myself in a position to work with
    something I don't.

    Of course, by doing that, I'd also be missing an opportunity to learn
    something new, so I can't be too annoyed with it, heh.

    Thanks, Joe and Peter!
    yawnmoth, May 24, 2009
    #4
  5. yawnmoth

    fulvius

    Joined:
    Sep 10, 2011
    Messages:
    1
    Joe Kesselman's syntax above worked for me once I removed the parentheses, as in: //strong[.='Name: ']/following-sibling::text[1] ... so to select the very next following sibling of any tag type, .../following-sibling::*[1]/... could be used, or for instance if you wanted to select not the very next div sibling, but rather the one after that, then .../following-sibling::div[2]/... should work.
    fulvius, Sep 10, 2011
    #5
    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:
    681
    Kathy Burke
    Aug 3, 2003
  2. Peter Rohleder
    Replies:
    3
    Views:
    7,540
    C. M. Sperberg-McQueen
    Jul 2, 2003
  3. Philipp Lenssen

    Select next sibling XPath?

    Philipp Lenssen, Nov 25, 2003, in forum: XML
    Replies:
    1
    Views:
    3,759
    Dimitre Novatchev
    Nov 25, 2003
  4. Brad
    Replies:
    6
    Views:
    903
    Joe Kesselman
    Jan 15, 2013
  5. Replies:
    11
    Views:
    651
    Fredrik Lundh
    Jan 23, 2006
Loading...

Share This Page