0
votes

I am testing some xpath expressions using http://www.freeformatter.com/xpath-tester.html (xpath 1.0)

I have this xml code

<urls>
    <url uri="http://example.com/pingtest.html">
        <elements>
            <element title="header" xpath="My header"></element>
        </elements>
    </url>
    <url uri="http://example.com/othertest.html">
        <elements>
            <element title="header3" xpath="Third header"/>
            <element title="header2" xpath="Second header"/>
        </elements>
    </url>
</urls>

Usually when I query xpath with //element/@title I actually get

Attribute='title="header"' Attribute='title="header3"' Attribute='title="header2"'

What I'm looking for is a way to get a count of elements by url. It could be something like this. When I query:

//urls/url/elements/count(element)

I should get (EDIT: as @Ian Roberts said, this query is valid in xpath 2.0):

Double='1.0' Double='2.0'

Is there a way to do this in a single xpath expression?

Some failing examples:

This returns the count of all element 3 (is not what I'm looking for)

count(//urls/url/elements/element)

This returns the count of all elements list 2 (neither what I'm looking for)

count(//urls/url/elements)

I need this because I need to know how many elements does the xml have for each url, so I can use this count afterwards

2
I don't understand the problem - //urls/url/elements/count(element) is a single XPath expression that returns a sequence of numbers representing the number of element elements under each url.Ian Roberts
My problem is that I'm using Xpath 1.0 and this expression is invalidFreefri
Oh, ok. The expression I quoted is valid XPath 2.0 and the output of your tester is the correct response for an XPath 2.0 processor, so I assumed 2.0 was ok.Ian Roberts

2 Answers

2
votes

You can use //urls/url/elements/count(element) with any XPath 2.0 or later or XQuery 1.0 or later implementation to get a sequence of integer values with the counts. If you only have XPath 1.0 available then you need to select //urls/url first in your host language and then you can for each returned item select count(elements/element).

1
votes

I believe that what you're looking for can't be done...

//element/@title searches the XML for paths containing an element with a title attribute; then returns an array of those attributes with their values.

//urls/url returns an array of xml elements for paths with element urls containing an element url. count(/elements/element) then performs the count function on the number of element elements under the elements element within each of the above paths.

Trying to put these into a single xpath would give us //urls/url/count(/elements/element). The issue here is the xpath is being used for two purposes:

  • to match a path to the element(s) we're interested in
  • to perform an aggregate function over items within that path.

However an xpath can only be used for one function or the other (e.g. depending on whether it were called from a match or a select statement.

As such (per @MartinHonnen's answer), you'd need to do a match first, then iterat through the results performing the select.