Tauseef Shaikh
Tauseef Shaikh

Reputation: 13

xPath Expression v1.0 [iterator if any]

Bit struggling to loop through dynamic occurrence of element names and extract the corresponding value. I am trying direct xPath expression.

My xml looks like:

<myXMLNode>
    <sunnyDay>YES</sunnyDay>
    <snowing>NO</snowing>   
    <temperatureInCelsius>
        <Date>2013-06-01</Date>
        <Date>2013-06-30</Date>
        <Date>2013-07-01</Date>
    </temperatureInCelsius>
</myXMLNode>

I want to extract all available Date element values having pipe separated, which keeps varying (at the moment 3 dates in my example above) example output: 2013-06-01|2013-06-30|2013-07-01

I tried below but no luck:

1. concat(//myXMLNode/temperatureInCelsius/Date[1], "_" ,//myXMLNode/temperatureInCelsius/Date[2], "_" ,//myXMLNode/temperatureInCelsius/Date[3])

2. //myXMLNode/temperatureInCelsius/Date[position()>0 or position()<=count(myXMLNode/temperatureInCelsius/Date)

3. //myXMLNode/temperatureInCelsius/Date[position()>0 and position()<=count(myXMLNode/temperatureInCelsius/Date)

Upvotes: 0

Views: 230

Answers (2)

Alejandro
Alejandro

Reputation: 1882

In XPath 1.0 there is no sequence or node set string value manipulation (i.e. string-join() from XPath 2.0+).

So, if you don't want a fixed concatenation like concat(date[1],'|',date[2]) and you are comfortable relying on XML serialization/parsing configuration (mainly about indentation and preserving whitespace only text nodes) you could use this XPath expression:

translate(normalize-space(/myXMLNode/temperatureInCelsius),' ','|')

Result:

2013-06-01|2013-06-30|2013-07-01

Test in here

Upvotes: 0

Mathias M&#252;ller
Mathias M&#252;ller

Reputation: 22647

The correct XPath expression to retrieve all relevant strings is

/myXMLNode/temperatureInCelsius/Date

or possibly

/myXMLNode/temperatureInCelsius/Date/text()

to select text nodes directly.

Concatenating those results with a separator such as | should be done not in XPath, but in the host language or environment that you are using. For instance, this is straightforward to do in Python:

>>> from lxml import etree
>>> document_string = """<myXMLNode>
...     <sunnyDay>YES</sunnyDay>
...     <snowing>NO</snowing>
...     <temperatureInCelsius>
...         <Date>2013-06-01</Date>
...         <Date>2013-06-30</Date>
...         <Date>2013-07-01</Date>
...     </temperatureInCelsius>
... </myXMLNode>"""
>>> root = etree.fromstring(document_string)
>>> dates = root.xpath("/myXMLNode/temperatureInCelsius/Date/text()")
>>> dates
['2013-06-01', '2013-06-30', '2013-07-01']
>>> "|".join(dates)
'2013-06-01|2013-06-30|2013-07-01'

Upvotes: 1

Related Questions