0

I'm trying to dynamically sense the structure of an xml file to determine unique nodes present

i.e. if I had

<?xml version="1.0" encoding="UTF-8"?>
<nsX:bookstore xmlns:nsX="http://namespace1" xmlns:nsY="http://namespace2">
  <nsX:bookList>
    <nsX:book category="COOKING">
      <nsX:title lang="en">Everyday Italian</nsX:title>
      <nsY:stock>1</nsY:stock>
    </nsX:book>
    <nsX:book category="CHILDREN">
      <nsX:title lang="en">Harry Potter</nsX:title>
      <nsX:edition lang="en">2</nsX:edition>
      <nsY:stock>0</nsY:stock>
    </nsX:book>
    <nsX:cd category="WEB">
      <nsX:albumTitle lang="en">XQuery Kick Start</nsX:albumTitle >
      <nsY:stock>1</nsY:stock>
    </nsX:cd>
    <nsX:tape category="WEB">
      <nsX:title lang="en">Learning XML</nsX:title>
      <nsY:year>1992</nsY:year>
    </nsX:tape>
  </nsX:bookList>
</nsX:bookstore>

and wanted to generate a list of my unique types of objects

book
cd
tape

I know how to find distinct-values of nodes, but what I need is to find distinct-local-names of nodes (which I am not aware of a command for).

I can use a loop to return the local name of each item, but that returns each local name separately making it impossible for me to use the distinct-values function.

I can use programmatic logic to handle the results of my xQuery, but I would much prefer to just return the correct information. Any advice would be greatly appreciated.

Ultimately, I would like to also be able to determine unique structure of the child nodes so that I could see that I have 2 different types of books (one with a title and one with an addition ) as well as a cd and a tape. It is easy enough to check to see if these things exist, but if I didn't know what I was looking for and I wanted to identify the unique types of objects based on their node structure, I would need to know how to find that.

David K
  • 213
  • 1
  • 2
  • 12

1 Answers1

3

It is as easy as distinct-values(/*/*/*/local-name()).

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • And use of string-join() would do the formatting too, `string-join(distinct-values(*/*/*/local-name()), ' ')` – Lingamurthy CS Apr 07 '15 at 13:05
  • So I can't believe I forgot you could use local-name in the path as opposed to as a function. The issue I am having is that when I try my call: distinct-values(//*:bookstore/*:bookList/local-name()[*:stock=1]) i get an error saying "node expected as input, xs:string found" – David K Apr 07 '15 at 13:12
  • I hope you want to use this: `distinct-values(//*:bookstore/*:bookList/*[*:stock=1]/local-name())`. As if you see, `local-name()/*` doesn't make sense(a string having a child element??). – Lingamurthy CS Apr 07 '15 at 13:18
  • Finally, that is what I'm doing wrong! Thanks so much @Lingamurthy CS . Your help and patience is greatly appreciated. – David K Apr 07 '15 at 13:23
  • @DavidK, just to make sure, you said "I forgot you could use local-name in the path as opposed to as a function" but that is not the right explanation, the expression `/*/*/*/local-name()` has a function call to the `local-name()` function in the last step of the path expression, that is a feature in XPath 2.0 and later and any XQuery version. See http://www.w3.org/TR/xquery/#id-path-expressions where it says "Since each step in a path provides context nodes for the following step, in effect, only the last step in a path is allowed to return a sequence of atomic values.". – Martin Honnen Apr 08 '15 at 08:49