2

I learned that every Xpath expression is also a valid Xquery expression. I'm using Oxygen 16.1 with this sample XML:

<actors>
    <actor filmcount="4" sex="m" id="15">Anderson, Jeff</actor>
    <actor filmcount="9" sex="m" id="38">Bishop, Kevin</actor>
</actors>

My expression is:

//actor/@id

When I evaluate this expression in Oxygen with Xpath 3.0, I get exactly what I expect:

15
38

However, when I evaluate this expression with Xquery 3.0 (also 1.0), I get the message: "Your query returned an empty sequence.

Can anyone provide any insight as to why this is, and how I can write the equivalent Xquery statement to get what the Xpath statement did above?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
mdslup
  • 105
  • 1
  • 1
  • 8
  • 2
    Are you sure you don't want `//actors/actor/@id`? – wst Jun 05 '15 at 20:44
  • 1
    `//actors/@id` most certainly will not return `15` or `38` when run against the content you provided with a compliant XPath engine. – Charles Duffy Jun 05 '15 at 20:57
  • 2
    Are you sure you haven't run `//actor/@id` or `//actors//@id` in the XPath engine? If you get any results on this document for `//actor/@id`, you should report an issue with the Oxygen developers. – Jens Erat Jun 05 '15 at 21:12
  • 1
    @Jens Erat you want to write //actors/@id – Kachna Jun 05 '15 at 21:53
  • Yes, I wanted to, of course. Can't edit the comment any more. It seems thet my guess of a typo was right anyway, reading the comments to the answer. – Jens Erat Jun 05 '15 at 21:54

1 Answers1

5

Other XQuery implementations do support this query

If you want to validate that your query (as corrected per discussion in comments) does in fact work with other XQuery implementations when entered exactly as given in the question, you can run it as follows (tested in BaseX):

declare context item := document { <actors>
    <actor filmcount="4" sex="m" id="15">Anderson, Jeff</actor>
    <actor filmcount="9" sex="m" id="38">Bishop, Kevin</actor>
</actors> };

//actor/@id

Oxygen XQuery needs some extra help

Oxygen XML doesn't support serializing attributes, and consequently discards them from a result sequence when that sequence would otherwise be provided to the user.

Thus, you can work around this with a query such as the following:

  • //actor/@id/string(.)
  • data(//actor/@id)

Below applies to a historical version of the question.

Frankly, I would not expect //actors/@id to return anything against that data with any valid XPath or XQuery engine, ever.

The reason is that there's only one place you're recursing -- one // -- and that's looking for actors. The single / between the actors and the @id means that they need to be directly connected, but that's not the case in the data you give here -- there's an actor element between them.

Thus, you need to fix your query. There are numerous queries you could write that would find the data you wanted in this document -- knowing which one is appropriate would require more information than you've provided:

  • //actor/@id - Find actor elements anywhere, and take their id attribute values.
  • //actors/actor/@id - Find actors elements anywhere; look for actor elements directly under them, and take the id attribute of such actor elements.
  • //actors//@id - Find all id attributes in subtrees of actors elements.
  • //@id - Find id attributes anywhere in the document.

...etc.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 1
    On correcting that, the XQuery engine should then return results, unless there are details (such as XML namespaces) you aren't showing us. – Charles Duffy Jun 05 '15 at 21:19
  • Thanks for these, I'm sorry about a typo that I made. My expression is, in fact, //actor/@id Charles, you mention this should return the id attribute values...in Xpath, it does. But when I use xquery, it says that it returns an empty sequence. Is this expected? I tried it in another editor, so it's not oxygen specific. – mdslup Jun 05 '15 at 21:20
  • 1
    Please test that you can reproduce the problem using **only** content included in the question -- ie. upload the snippet you gave here as a complete document, and see if it still occurs. – Charles Duffy Jun 05 '15 at 21:21
  • 1
    @mdslup, ...I've amended the question to show exactly how I'm testing (using XQuery 3.0 extensions to set your document as context item; FYI, the engine I use is BaseX). – Charles Duffy Jun 05 '15 at 21:25
  • 1
    (that said, use of BaseX is only relevant for availability of `declare context item`, which is a relatively recent language feature; otherwise, this will behave identically with any engine available). – Charles Duffy Jun 05 '15 at 21:30
  • Here is a google drive link to to the file: https://drive.google.com/file/d/0By5gokbK9aHTcEJ6b05PS0hkdE0/view?usp=sharing Additionally, here is a link to a screenshot of when I try to run the query.: https://drive.google.com/file/d/0By5gokbK9aHTYWh0SjR1eTZXSFU/view?usp=sharing – mdslup Jun 05 '15 at 22:28
  • 1
    Can you reproduce on any non-proprietary engine? I'm certainly not about to sign a license agreement and put myself on someone's marketing list to reproduce a product bug. – Charles Duffy Jun 05 '15 at 22:31
  • If you tell me what you're using, I'll download it, just so we can communicate more clearly. – mdslup Jun 05 '15 at 22:31
  • I tried BaseX - it worked. I also tried a trial version of another proprietary software called Stylus Studio. That worked too. Astonishingly, this must be a bug(?) in Oxygen. Thanks for helping me pin this down Charles...I think I've reached the limit of what I can solve in this thread. – mdslup Jun 05 '15 at 22:54
  • 1
    A silly question -- do **any** queries return data? `//actor`, for instance? I'd almost suspect something at the UI layer where the queries might not be getting executed against the correct document at all. – Charles Duffy Jun 05 '15 at 23:01
  • 1
    If the answer is "yes", and `//actor` works but `//actor/@id` does not, I'd be tempted to try `//actor/@id/string(.)` and see if the problem is rendering query results to the UI (though that would be surprising, it'd be less surprising than having that serious a bug al the way at the engine). – Charles Duffy Jun 05 '15 at 23:04
  • 1
    Yeah, //actor works...I found this bug because I was writing a larger xquery, and was stumped by the error...I kept debugging until I was left with this ridiculously simple query that was failing. Wow, your //actor/@id/string(.) works in Oxygen! How bizarre. You know, I went back and tried my original complicated query in XBase...it worked immediately, and I like how it formats it output much better than Oxygen. I'll consider pursuing more about the oxygen xquery system later, but for now, I can accomplish what I need to in xbase. Charles, thanks for your guidance. – mdslup Jun 05 '15 at 23:43
  • Glad to help. Incidentally, if there ends up being a publicly-visible bug report to Oxygen over this, I'd be curious to see a link, just to have confirmation about the details of the issue came about; I have my guesses (re: attributes without an element being non-renderable at the UI level -- which is why I suggested the `string(.)` workaround), but finding out how far off that guess was would be interesting. – Charles Duffy Jun 06 '15 at 00:11
  • Here was Oxygen's official response:Note that this is not a bug, just a misuse of XQuery. You are using an XPath that matches some attributes. As an XPath result this is well and fine. However XQuery can only output XML nodes as result and the two @id attributes that are matched by the XPath you give it won't do just by themselves, they need to be attached to something or converted. If you just want the values of the attributes in XQuery try: data(//actor/@id) – mdslup Jul 01 '15 at 20:11
  • I've tried to adjust both the question and its answer to be more helpful to folks hitting the same behavior in Oxygen in the future. – Charles Duffy Jul 01 '15 at 20:22