Pergunta

I have an xml where element names under client/product/analytics/count is unknown. Is there a way I can traverse and get each element name and it's equivalent value?

below is my xml data

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="client.xsl"?>
<client version="1.0">
    <product>
        <analytics>
            <count>
                <SkinsCount>14</SkinsCount>
                <AppsCount>6</AppsCount>
                <AbspCount>2</AbspCount>
            </count>
        </analytics>
    </product>
</client>

part of my xsl code

...
<xsl:variable name="NA" select="'no data'" />
<h3><span style="color:#328aa4"><a name="_analytics" href="#_top">Analytics </a></span></h3>                
    <h3>Count</h3>  

    <dd><br/>
        <xsl:choose>
            <xsl:when test="client/product/analytics/count/*">
                <table border="1">
                    <tbody>
                        <xsl:if test="client/product/analytics/count/AbspCount"><tr>
                            <th align="left">Absp Count</th><td><xsl:value-of select="client/product/analytics/count/AbspCount"/></td></tr>
                        </xsl:if>
                        <xsl:if test="client/product/analytics/count/SkinsCount"><tr>
                            <th align="left">Skins Count</th><td><xsl:value-of select="client/product/analytics/count/SkinsCount"/></td></tr>
                        </xsl:if>
                        <xsl:if test="client/product/analytics/count/AppsCount"><tr>
                            <th align="left">Apps Count</th><td><xsl:value-of select="client/product/analytics/count/AppsCount"/></td></tr>
                        </xsl:if>                   
                    </tbody>
                </table>
            </xsl:when>
            <xsl:otherwise>
                <br/><xsl:value-of select="$NA"/>
            </xsl:otherwise>
        </xsl:choose>           
    </dd>
...

for which current output snapshot when I specifically use known element names like AppsCount, AbspCount & SkinsCount

enter image description here

Foi útil?

Solução

Try something like:

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

<xsl:template match="/">
    <table border="1">
         <xsl:for-each select="client/product/analytics/count/*">
             <tr>
                 <th align="left"><xsl:value-of select="name()"/></th>
                 <td><xsl:value-of select="."/></td>
             </tr>
         </xsl:for-each> 
     </table>
 </xsl:template>

</xsl:stylesheet>

Outras dicas

You should probably start off by simply selecting all the child elements of the count element

<xsl:apply-templates select="client/product/analytics/count/*" />

Then you would have a single template to match such elements, and output the element name and value, like so

<xsl:template match="count/*">
    <tr>
        <td><xsl:value-of select="local-name()" /></td>
        <td><xsl:value-of select="." /></td>
    </tr>
</xsl:template>

Of course, this will output the element name without spaces (i.e as "SkinsCount"). If the element names always ended in "Count", you could do this

<xsl:value-of select="concat(substring-before(local-name(), 'Count'), ' Count')" />

But if you were using XSLT 2.0, you could you make use of xsl:analyze-string to split up the element name based of the capitalised letters.

Try this XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes" />

    <xsl:template match="/">
        <table>
            <xsl:apply-templates select="client/product/analytics/count/*" />
        </table>
    </xsl:template>

    <xsl:template match="count/*">
        <tr>
            <td>
                <xsl:analyze-string select="local-name()" regex="[A-Z][a-z0-9]*">
                    <xsl:matching-substring>
                        <xsl:value-of select="concat(., ' ')" />
                    </xsl:matching-substring>
                </xsl:analyze-string>
            </td>
            <td><xsl:value-of select="." /></td>
        </tr>
    </xsl:template>
</xsl:stylesheet>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top