Reputation: 3829
I have the following structure to XML file:
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property/>
<Property/>
</Control>
<Control id="GroupHeading2">
<Property/>
<Control id="TextBox">
<Property/>
<Property/>
</Control>
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
I am trying to deserialize this into C# object, but I don't need to preserve the hierarchy (which is making it difficult for me to deserialize).
Is there XSL that can transform this to un-nest the Controls, and if possible add an attribute to any child Control with ParentId=""?
Thank you for any guidance!
Upvotes: 3
Views: 995
Reputation: 60414
The following stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- first-level control elements -->
<xsl:template match="Control">
<Control>
<xsl:copy-of select="@*|*[not(self::Control)]" />
</Control>
<xsl:apply-templates select="Control" />
</xsl:template>
<!-- nested control elements -->
<xsl:template match="Control/Control">
<Control ParentId="{../@id}">
<xsl:copy-of select="@*|*[not(self::Control)]" />
</Control>
<xsl:apply-templates select="Control" />
</xsl:template>
</xsl:stylesheet>
Applied to the following document (same as original with one additional level of nesting for demonstration purposes):
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
<Control id="TextBox">
<Property />
<Property />
<Control id="Grandchild">
<Property />
</Control>
</Control>
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
Produces an output with no nested <Control>
elements:
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
</Control>
<Control ParentId="GroupHeading2" id="TextBox">
<Property />
<Property />
</Control>
<Control ParentId="TextBox" id="Grandchild">
<Property />
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
Upvotes: 1
Reputation: 43168
This template should get you started. I ran it against .NET 2.0.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="*"/>
</xsl:element>
</xsl:template>
<xsl:template match="Form">
<Form>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="//Control"/>
</Form>
</xsl:template>
<xsl:template match="Control">
<Control>
<xsl:if test="ancestor::Control/@id">
<xsl:attribute name="ParentID"><xsl:value-of select="ancestor::Control/@id"/></xsl:attribute>
</xsl:if>
<xsl:copy-of select="*|@*"/>
</Control>
</xsl:template>
</xsl:stylesheet>
This is the output (indented for readability).
<INSTANCE>
<Sections>
<Section>
<Forms>
<Form>
<Control id="GroupHeading1">
<Property />
<Property />
</Control>
<Control id="GroupHeading2">
<Property />
<Control id="TextBox">
<Property />
<Property />
</Control>
</Control>
<Control ParentID="GroupHeading2" id="TextBox">
<Property />
<Property />
</Control>
</Form>
</Forms>
</Section>
</Sections>
</INSTANCE>
Upvotes: 1
Reputation: 46415
Given XML, the XmlSerializer
can produce a graph of objects that hold the same instance data.
This is known as XML de-serialization
You need to look here :
Upvotes: 2