XPath 3.1 expression to collect attributes as name/value maps for each selected node

901 Views Asked by At

XPath 3.1 supports a new map feature that allows maps in the result sequences. https://www.w3.org/TR/xpath-31/#id-maps

For example, here is the valid XPath 3.1 expression that returns a hardcoded sequence of 2 maps:

(map {'a':1,'b':2,'c':3}, map {'x':-3,'y':-2,'z':-1})

I am trying to use this feature to collect node attributes as list of maps.

For example, for the given xml:

<root>
  <node a="1" b="2" c="3"/>
  <node x="-3" y="-2" z="-1"/>
</root>

How can I craft a simple XPath expression to get the following result:

[{'a':1,'b':2,'c':3}, {'x':-3,'y':-2,'z':-1}]
1

There are 1 best solutions below

4
On BEST ANSWER

With an element as context item you can form a map of the attributes like this:

map:merge(@* ! map{local-name(): string()})

To get a sequence of maps for a sequence of elements $in, you can do

$in ! map:merge(@* ! map{local-name(): string()})

To get an array of maps for a sequence of elements $in, you can do

array { $in ! map:merge(@* ! map{local-name(): string()}) }

In your example you are also converting the attribute values to numbers, so you would use xs:integer(.) in place of string(). But you haven't said what you want to do if there are non-numeric attributes.