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

Go To StackoverFlow.com

3

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.

2012-04-05 21:25
by Robert Harvey


2

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>
2012-04-05 21:36
by Daniel Haley
Thanks. Now I just have to figure out how to execute it against the original XSD. :P As you might have guessed, I have zero experience with XSLT, although I do know what it's purpose is. I bow to the great XSLT gurus who are much more enlightened than I - Robert Harvey 2012-04-05 21:37
@RobertHarvey - I'm definitely no guru, but I'm glad I could help - Daniel Haley 2012-04-05 21:52
@??? - Why the downvote? - Daniel Haley 2012-04-11 16:08


0

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 :)

2012-04-06 15:54
by InfantPro'Aravind'
I would suggest you try your XSLT against one XSD which has some global types as well; a simple one, such as the one posted here on SO. You'll see that yours doesn't work, at least compared with @DevNull's... I'll let you figure out why... then maybe you can update your post - Petru Gardea 2012-04-06 19:29
@PetruGardea, It works for the OPs question .. If element has complex type defined within, then my code doesn't work I know that .. that is because I am ignoring all the ELEMENT nodes within <xs:element/>.. instead if they define complextype else where and use it as type for Element it should work - InfantPro'Aravind' 2012-04-07 09:22
@PetruGardea, I will update my answer rightaway .. to make it work for example you have mentioned - InfantPro'Aravind' 2012-04-07 09:22
is the downvoter having enough courtesy to let me know the reason for downvoting? - InfantPro'Aravind' 2012-04-11 16:05
Ads