3

in an xml schema nesting of <item>s is allowed unbounded e.g. in an unordered list of items (which is <randlist> for random list). These items may contain subitems that may be sublisted using <item> as a subelement within another list element such as <randlist> or <seqlist> for ordered lists.

Now I want to detect a nesting of more then 3 nesting depth levels in a document to apply some constraints on it. Using xpath this is what should be allowed unconditioned:

randlist//item

or

randlist//item//item

or

randlist//item//item//item

but

randlists with more then 3 item nesting depth levels should be prohibited, e.g.

randlist//item//item//item//item

How I can use xpath to formulate an expression that expresses a nesting of elements beyond the third level?

thank in advance

sorry people! so here the example goes

<randlist> <!-- first level (not nested at all): allowed -->
    <item>
        This is the first item of an unordered enumeration of items that are prosa altogether.
    </item>
    <item>
        <randlist> <!-- second level (nested): allowed -->
            <item>
                This is the first item of an unordered enumeration of items that are prosa altogether.
            </item>
            <item>
                Another item with some information in the nested unordered list.
            </item>
            <item>
                <seqlist> <!-- third level (double nested): allowed -->
                    <item>
                        This is the first item of an ordered enumeration of items (it may be shown with the number 1).
                    </item>
                    <item>
                        This is the second item of an ordered enumeration of items (it may be shown with the number 2).
                        <randlist> <!-- fourth level (triple nested): should be prohibited -->
                            <item>
                                This is the first item of an unordered enumeration of items.
                            </item>
                            <item>
                                This is the second item of an unordered enumeration of items.
                            </item>
                        </randlist>
                    </item>
                    <item>
                        This is the third item of an ordered enumeration of items (it may be shown with the number 3).
                    </item>
                </seqlist>
            </item>
        </randlist>
    </item>
</randlist>

I need to detect more then 3 levels of item lists, i.e. the fourth level and more. I need something like e.g. randlist[count(nesting(item))>3], if there were a function like "nesting" in xpath.

IlkerS
  • 33
  • 5

3 Answers3

2

What's wrong with the expression that you provided yourself:

randlist//item//item//item//item

This will select any item that has three or more item ancestors.

More efficient might be

randlist//item[count(ancestor::item) > 2]

but that depends on the XPath processor you are using.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • oh this seems to be the expression I was looking for item[count(ancestor::item) > 2] . thanks I will try it out – IlkerS Oct 19 '15 at 16:12
  • and when I think further: you are right! the expression with the four items will also detect nestings with five or more item elements. I am relatively new to xpath so I sometimes need my time :) – IlkerS Oct 19 '15 at 16:26
1

From your question it is a little tricky to know exactly what your desired output is, but I think that one of the following suggestions should be sufficient, or help you reach your goal.

As a general example, you can count the number of elements past a certain level of nesting by passing a set of nodes/elements to the count XPath function. For example:

XML

<randlist>
    <item>
        <content>Example Content</content>
        <subitem>
          <p>Content</p>
          <p2>More Content</p2>
        </subitem>
    </item>
</randlist>

XPath

count(randlist/item//*)

This will count the number of elements that are descendants of item elements that are direct children of randlist elements. The double-slash // means that the XPath searches for descendants, and the * operator is a wildcard which matches any elements, regardless of element name. It will therefore return 4 - beacuse there are 4 elements: content, subitem, p and p2.

In your case, I think you are looking to detect randlist and seqlist elements that are located within three levels of nesting of item. If you want to detect this occurrence, you could use:

count(randlist//item//item//item//randlist|randlist//item//item//item//seqlist)

The | operator computes the union of the two sets. If you want to detect the occurrence of any element located within three levels of nesting of item, again, you should use the wildcard operator *:

count(randlist//item//item//item//*)
gtlambert
  • 11,711
  • 2
  • 30
  • 48
  • thank you for your answer! the problem is that I want to detect more than 3 levels of nesting. so it is not a fix number. I think I will test something like randlist//item[count(ancestor::item) > 3] as suggested below as soon as I am in the office and work with XmlSpy again :) – IlkerS Oct 19 '15 at 16:16
1

Assuming that randlist is always the root element of the XML document, this is one possible XPath expression to check if it contains more than 3 level nested item elements :

randlist[.//item[count(ancestor::item)>=3]]
har07
  • 88,338
  • 12
  • 84
  • 137