Robert Harvey
Robert Harvey

Reputation: 180808

How do I convert these embedded elements into attributes of the parent element?

I have a large XSD, with elements that look like this:

<xs:element name="ProgramName" type="xs:string" minOccurs="0">
  <xs:annotation>
    <xs:documentation>PN</xs:documentation> 
  </xs:annotation>
</xs:element>
<xs:element name="TestItem" type="xs:string" minOccurs="0">
  <xs:annotation>
    <xs:documentation>TA</xs:documentation> 
  </xs:annotation>
</xs:element>

I would like to collapse the <documentation> element into an attribute of the grandparent element, like this:

<xs:element name="ProgramName" type="xs:string" minOccurs="0" code="PN">
</xs:element>
<xs:element name="TestItem" type="xs:string" minOccurs="0" code="TA">
</xs:element>

How could this be done with XSLT? Alternatively, is there a better (read: simpler) way to do it than XSLT?

The resulting XSD will be used with XSD.EXE to create a C# class, for serialization and deserialization purposes. The original XSD cannot be used this way, because XSD.EXE drops all of the annotation elements, so the information contained in those annotations is lost.

Upvotes: 3

Views: 160

Answers (2)

Rookie Programmer Aravind
Rookie Programmer Aravind

Reputation: 12154

This Just another answer :)

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

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

  <xsl:template match="node()[local-name()='element']">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()[local-name()!='annotation']"/>
      <xsl:for-each select="node()[local-name()='annotation']/node()[local-name()='documentation']">
        <xsl:attribute name="code">
          <xsl:value-of select="."/>
        </xsl:attribute>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Indeed a very good thought of using XSLT for rearranging nodes rather than doing it manually :) I always make use of XSLT ..
We can even use it to generate sample XMLs from XSD .. if XSD is with bearable size :)

Upvotes: 0

Daniel Haley
Daniel Haley

Reputation: 52858

This is how I'd do it:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*[xs:annotation]">
    <xsl:copy>
      <xsl:attribute name="code"><xsl:value-of select="xs:annotation/xs:documentation"/></xsl:attribute>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>    
  </xsl:template>

  <xsl:template match="xs:annotation"/>      

</xsl:stylesheet>

Upvotes: 2

Related Questions