What makes an XPath (string)?

Stefan_E
2009-11-11
2012-10-08
  • Stefan_E
    Stefan_E
    2009-11-11

    I'm a newbie to XQuery and XPath. Posted below question over at Oxygen, but
    didn't yet get the reply I wanted :-(

    I'm trying to compare two XML structures. The problem I now have: What exactly
    makes an XPath (string?)?

    I have the following code:

    declare variable $x1 := <top>
    <rec>
    <d1>25</d1>
    <d2>10</d2>
    </rec>
    </top>;
    declare variable $x2 := <top>
    <rec>
    <d1>30</d1>
    <d2>10</d2>
    </rec>
    </top>;
    for $node in $x1/rec
    return for $elem in $node/
    return if ($elem = $x2/rec/
    )
    then (<match>{$elem}</match>)
    else (<diff>{$elem}</diff>)

    which produces

    <diff> <d1>25</d1> </diff> <match> <d2>10</d2> </match>

    So far so good, but it took me a while to get there. Specifically, in my
    original trials, I had something like

    return if ($elem = $x2/rec/local-name($elem))
    then (<match>{$elem}</match>)
    else (<diff>{$elem}</diff>)

    What confuses me:

    • Checking with the debugger, I find local-name(elem) = 'd1'
    • but also $x2/rec/local-name($elem) evaluates to 'd1' (rather than what I expected: 30)
      Hence, what I picture for myself as an XPath string seems to be the wrong
      concept. But what is the right one?

    My programming background is mostly perl, where I would happily expect a
    string expansion before evaluation. But if this is not the case in XQuery: Why
    does the interpreter not bark on the apparently useless part of the path
    string ($x2/rec)?

    The question is really two-fold:

    • what's going on in above example?
    • where do I learn the underlying concepts? The O'Reilly book on XQuery doesn't really explain the underlying grammatical principles (or I didn't find them...)

    Thanks for your help!
    Stefan

     
  • Michael Kay
    Michael Kay
    2009-11-11

    This forum is intended for questions specific to the Saxon product: a good
    place for general XSLT and XPath coding help is the xsl-list at
    mulberrytech.com (although you're actually in XQuery territory here, for which
    there is another list - talk at x-query.com).

    The "/" operator means "evaluate the rhs operand once for every item in the
    sequence produced by evaluating the lhs operand, with that item as the context
    item". So

    $x2/rec/local-name($elem)

    means evaluaye local-name($elem) once for every element in $x2/rec. There is
    only one element in $x2/rec, so local-name($elem) gets evaluated exactly once,
    and returns, of course, the local name of the node in variable $elem. It's
    usually rather pointless to have an expression on the rhs of "/" than doesn't
    depend on the context item, but it's not banned: there are plenty of
    expressions that are pointless, like $x * 1, and it's a general principle of
    modern language design that being pointless is not in itself justification for
    making something illegal.

    You were thinking, of course, that the local name of $elem would be used as a
    NameTest in the next step of the path expression. Well, the language doesn't
    work that way: you can't generate bits of syntax on the fly by evaluating
    expressions, and then have that syntax parsed and evaluated again. It's
    surprising what people sometimes expect: there was a post on the Wrox forum
    today where someone wanted to use a variable containing the string "and" or
    "or" in place of the actual operator. I guess there are some completely
    interpretive shell languages that allow that, but XPath isn't one of them.

     
  • Stefan_E
    Stefan_E
    2009-11-12

    Hi Michael,

    thanks for your detailed reply. Your rhs/lhs explanation makes a lot more
    sense than much of what I've read online and in the XQuery book :-). Once such
    conceptual things are clear, the rest probably goes down more easily ...