0

Trying to query e-mail addresses using xpath and xquery but am not getting any results when

simple query:

xquery version "3.1";

for $contact in db:open("sample")

return $contact

data:

<Objs xmlns="http://schemas.microsoft.com/powershell/2004/04" Version="1.1.0.1">
  <Obj RefId="0">
    <TN RefId="0">
      <T>System.Management.Automation.PSCustomObject</T>
      <T>System.Object</T>
    </TN>
    <MS>
      <S N="First Name">a</S>
      <S N="Last Name">b</S>
      <S N="Emails">a@b;b@a.com</S>
      <S N="Phones">123 456-8904</S>
      <S N="Company Name"/>
    </MS>
  </Obj>
  <Obj RefId="1">
    <TNRef RefId="0"/>
    <MS>
      <S N="First Name">c</S>
      <S N="Last Name">c</S>
      <S N="Emails">e@f.com</S>
      <S N="Phones">123456-3532;563 346-3453</S>
      <S N="Company Name"/>
    </MS>
  </Obj>
</Objs>

I'm looking to get Objs/Obj/MS/S[N="emails"]/text() along those lines, for the actual content of the attribute.

  • 1
    What XQuery engine is in use? Overall, you need to specify path to the XML documents in an XML database. – Yitzhak Khabinsky Dec 09 '20 at 16:42
  • I'm using basex, but might try something else. I think the reference book is general enough to work with most anything. – Nicholas Saunders Dec 09 '20 at 16:45
  • 1
    BaseX is a great XML database. It supports latest XQuery 3.1 – Yitzhak Khabinsky Dec 09 '20 at 16:46
  • 1
    https://docs.basex.org/wiki/Databases – Yitzhak Khabinsky Dec 09 '20 at 16:47
  • 1
    Your question is rather confusing, because attributes don't have text node children. You've told us what you want to get by showing us some code which presumably doesn't work, so we have to guess what you intended it to do. The most obvious error is that you're ignoring the fact that the elements are in a namespace; you've also ignored the difference between "emails" and "Emails", and you've used `N` rather than `@N`. – Michael Kay Dec 09 '20 at 19:12

2 Answers2

2

I don't have your XML database...

You can try something along the following.

XQuery

xquery version "3.1";

declare namespace ns1="http://schemas.microsoft.com/powershell/2004/04" Version="1.1.0.1";

for $contact in db:open("sample")//ns1:S[@N="Emails"]/text()
return $contact
Yitzhak Khabinsky
  • 18,471
  • 2
  • 15
  • 21
1

There are two problems, if you want a predicate to check an attribute use Objs/Obj/MS/S[@N="emails"]/text() and not Objs/Obj/MS/S[N="emails"]/text(). And of course with namespaces and the default settings the path selects elements in no namespace while your document has them in a namespace so you in XQuery you can declare

declare default element namespace "http://schemas.microsoft.com/powershell/2004/04";

and then select e.g. /Objs/Obj/MS/S[@N="Emails"]/text() (another slight correction is the string literal Emails instead of emails.

Note that in XQuery the declared default element namespace is used both for path selection as well as for output elements so you might end up with result elements in that namespace.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110