xsl transform of dataset.writexml XML
I have a scenario where I am exporting a .net dataset to an xml file, but I want to transform the stucture of the xml output to a more hierarchical structure. Below is the format of the dataset as exported by dataset.xmlwrite() method.
<NewDataSet>
<Table>
<id>100</id>
<empname>Joe Smith</empname>
<phone>111-111-1111</phone>
<mobile>222-222-2222</mobile>
</Table>
<Table>
<id>101</id>
<empname>Ann Jensen</empname>
<phone>111-111-0000</phone>
<mobile>222-222-0000</mobile>
</Table>
<NewDataSet>
I want to convert it to the below structure. I am a newbie at xsl transforms and I am not sure how keep the <Table>
element from repeating for every record in the dataset.
<NewDataSet>
<Table>
<employee id="100">
<empname>Joe Smith</empname>
<phone>111-111-1111</phone>
<mobile>222-222-2222</mobile>
</employee>
<employee id="101">
<empname>Ann Jensen</empname>
<phone>111-111-0000</phone>
<mobile>222-222-0000</mobile>
</employee>
</Table>
<NewDataSet>
I tried using a combination of xsl:for-each and xsl:if statements to get what I wanted, but so far I have not been a开发者_Go百科ble to get it to work. Any assistance would be greatly appreciated.
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Table[1]">
<Table>
<xsl:apply-templates select="../Table/id"/>
</Table>
</xsl:template>
<xsl:template match="Table[position()>1]"/>
<xsl:template match="Table/id">
<employee id="{.}">
<xsl:apply-templates select=
"following-sibling::node()"/>
</employee>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document (corrected to be well-formed):
<NewDataSet>
<Table>
<id>100</id>
<empname>Joe Smith</empname>
<phone>111-111-1111</phone>
<mobile>222-222-2222</mobile>
</Table>
<Table>
<id>101</id>
<empname>Ann Jensen</empname>
<phone>111-111-0000</phone>
<mobile>222-222-0000</mobile>
</Table>
</NewDataSet>
produces the wanted, correct result:
<NewDataSet>
<Table>
<employee id="100">
<empname>Joe Smith</empname>
<phone>111-111-1111</phone>
<mobile>222-222-2222</mobile>
</employee>
<employee id="101">
<empname>Ann Jensen</empname>
<phone>111-111-0000</phone>
<mobile>222-222-0000</mobile>
</employee>
</Table>
</NewDataSet>
Explanation:
The identity rule copies every node "as-is".
The first
Table
element is matched by an overriding template. This creates the onlyTable
in the result and applies templates to the children of allTable
elements.The
id
element is matched by an overriding template, that converts it to anemployee
element having anid
attribute with the value of theid
element. This also applies templates from inside theemployee
element to all other siblings ofid
and they are copied as-is by the identity template.
this should do the trick
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Table>
<xsl:for-each select="/NewDataSet/Table">
<employee>
<xsl:attribute name="id"><xsl:value-of select="id/."/></xsl:attribute>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name() = 'id' "/>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</employee>
</xsl:for-each>
</Table>
</xsl:template>
</xsl:stylesheet>
精彩评论