0
votes

I am new to XPath and XML. I was wondering if there is an XPath expression to select all the attribute names and their respective values from an entire XML document.

As a simpler example to what I have:

<bookstore>
    <book category="COOKING">
        <title lang="en">Everyday Italian</title>
        <author>Giada De Laurentiis</author>
        <year>2005</year>
        <price>30.00</price>
            <money currency="Dollars"></money>
    </book>
    <book category="CHILDREN">
        <title lang="en">Harry Potter</title>
        <author>J K. Rowling</author>
        <year>2005</year>
        <price>29.99</price>
            <money currency="Dollars"></money>
    </book>
    <book category="WEB">
        <title lang="en">XQuery Kick Start</title>
        <author>James McGovern</author>
        <author>Per Bothner</author>
        <author>Kurt Cagle</author>
        <author>James Linn</author>
        <author>Vaidyanathan Nagarajan</author>
        <year>2003</year>
        <price>49.99</price>
            <money currency="Euros"></money>
    </book>
        <book category="WEB">
        <title lang="en">Learning XML</title>
        <author>Erik T. Ray</author>
        <year>2003</year>
        <price>39.95</price>
            <money currency="Dollars"></money>
    </book>
</bookstore>

I want this:

category : COOKING
lang : en
currency : Dollars

category : CHILDREN
lang : en
currency : Dollars

category : WEB
lang : en
currency : Euros

category : WEB
lang : en
currency : Dollars

The thing is I want this expression to work for any XML document. Any other suggestions as to how I can do this are welcome as well. Thank you.

1
It is possible.. Please provide an example input and the expected output.Lingamurthy CS
Strictly speaking, the value of an attribute is not a node and cannot be selected by an XPath expression. But it is certainly possible to output a list of name/value pairs using XSLT. Show us (at least) the expected output.michael.hor257k
I provided a simpler example. My document is to large to share but the goal is the same. Thank you.pseudorandom
"I want this expression to work for any XML document" In your example, there is a clear grouping by book. That cannot work for any document - XML is far more extensible than that.michael.hor257k
@michael.hor257k: +1 for your helpful explanations. However, just because something is not a node doesn't mean it can't be "selected" (in some sense) by an XPath expression. E.g. string(/*/book[1]/@category) I'm sure you know this, but the way you phrased it might give the unaware a mistaken impression.LarsH

1 Answers

1
votes

This will work for your input (after you fix the mismatching tags <money> and </currency>!) and other reasonably similar XML documents - but it cannot be guaranteed to work with any XML document:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/*/*">
    <xsl:for-each select=".//@*">
        <xsl:value-of select="concat(name(), ': ', ., '&#10;')"/>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
</xsl:template>

</xsl:stylesheet>

OTOH, this will work with any XML - but the output will be just a single list of all attribute name/value pairs in the entire document, with no separation:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:template match="/">
    <xsl:for-each select="//@*">
        <xsl:value-of select="concat(name(), ': ', ., '&#10;')"/>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Result

category: COOKING
lang: en
currency: Dollars
category: CHILDREN
lang: en
currency: Dollars
category: WEB
lang: en
currency: Euros
category: WEB
lang: en
currency: Dollars