How do I convert these embedded elements to the 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 an element <documentation>

into an attribute of the grandparent element, for example:

<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 can this be done with XSLT? Alternatively, is there a better (read: simpler) way to do this 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 in this way because it XSD.EXE

removes all annotation elements, so the information contained in those annotations is lost.

+3


source to share


2 answers


This is how I would 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>

      

+2


source


This is 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, it is a very good idea to use XSLT to reorder nodes rather than doing it manually :) I always use XSLT ..
We can even use it to generate XML samples from XSD .. if the XSD is sized correctly :)

0


source







All Articles