Nested XML processing with XSLT
I have an XML document with following structure:
- root element DataModel can have children Node, Integer and String
- Node element can have children Node, Integer and String as well
E.g.:
<DataModel>
<String name="a">aaa</String>
<Integer name="b">bbb</Integer>
<Node name="n1">
<String name="k">kkk</String>
<Integer name="l">lll</Integer>
<Node name="n2">
<String name="x">xxx</String>
</Node>
</Node>
</DataModel>
I'd like to process this XML, flattening the output, but bringing the hierarchical structure in the naming, like so:
<table>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<tr>
<td>a</td>
&l开发者_JS百科t;td>aaa</td>
</tr>
<tr>
<td>b</td>
<td>bbb</td>
</tr>
<tr>
<td>n1.k</td>
<td>kkk</td>
</tr>
<tr>
<td>n1.l</td>
<td>lll</td>
</tr>
<tr>
<td>n1.n2.x</td>
<td>xxx</td>
</tr>
</table>
Any ideas how to do this?
Use this template:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="DataModel">
<table>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<xsl:apply-templates select="*"/>
</table>
</xsl:template>
<xsl:template match="*">
<tr>
<td>
<xsl:for-each select="ancestor::Node">
<xsl:value-of select="concat(@name, '.')"/>
</xsl:for-each>
<xsl:value-of select="@name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="Node">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Applied to XML:
<DataModel>
<String name="a">aaa</String>
<Integer name="b">bbb</Integer>
<Node name="n1">
<String name="k">kkk</String>
<Integer name="l">lll</Integer>
<Node name="n2">
<String name="x">xxx</String>
</Node>
</Node>
</DataModel>
Will produce desired output:
<table>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<tr>
<td>a</td>
<td>aaa</td>
</tr>
<tr>
<td>b</td>
<td>bbb</td>
</tr>
<tr>
<td>n1.k</td>
<td>kkk</td>
</tr>
<tr>
<td>n1.l</td>
<td>lll</td>
</tr>
<tr>
<td>n1.n2.x</td>
<td>xxx</td>
</tr>
</table>
This template supports any depth of nesting, thanks to for-each with ancestor:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="DataModel">
<table>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<xsl:apply-templates select="*"/>
</table>
</xsl:template>
<xsl:template match="Node">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="String|Integer">
<tr>
<td>
<xsl:for-each select="ancestor::Node">
<xsl:value-of select="concat(@name, '.')"/>
</xsl:for-each>
<xsl:value-of select="@name"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
<xsl:apply-templates select="*"/>
</xsl:template>
</xsl:stylesheet>
so the result is exactly as required, including the last row:
...
<tr>
<td>n1.n2.x</td>
<td>xxx</td>
</tr>
</table>
精彩评论