Detect XSD Code Generation Issues

The XSD.EXE command-line tool will generate .NET types from a set of XML Schema files.

However, certain constructs in the XSD will result in faulty .NET code. In particular, <xsd:choice> elements with children that are not exclusively <xsd:element>s are quite likely to have issues in the generated class.

I found that the following XSLT stylesheet proves useful in flagging up potentially-troublesome Schema fragments.

It's not perfect but it's better than scanning schema by eye.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xsd">

<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">

<html>

<head>

<title>Xml Schema Code Generation Issue Report</title>

<style>

BODY { margin-left: 10px;

margin-right:10px;

font-family:"Verdana", sans-serif;

font-size:x-small;

}

#content { font-size:x-small;

padding-bottom: 2em;

}

.main { position:absolute;

top:80px;

left:80px;

}

#links { position:absolute;

top:158px;

left:45px;

}

dt { font-weight:bold;}

.footer { position:absolute;

top:468px;

left:18px;

width:130px;

color:black;

font-weight:bold;

}

.ie4footer { position:absolute;

top:400px;

left:-160px;

width:130px;

color:black;

font-weight:bold;

}

A:link { color:rgb(78,72,135) }

A:visited { color:rgb(128,128,200) }

A:active { color:rgb(241,96,67) }

A:hover { color:rgb(241,96,67) }

#links A:link { color:rgb(78,72,135); text-decoration:none; }

#links A:visited { color:rgb(78,72,135); text-decoration:none; }

#links A:active { color:white }

#links A:hover {color:white}

.footer A:link { color:rgb(255,170,87) }

.footer A:visited { color:rgb(255,170,87) }

.footer A:active { color:white }

.footer A:hover {color:white}

#editor { position:absolute;

top:80px;

left:200px;

}

#editor DIV { font-size:xx-small;

font-style:italic;

}

.new { background-color:rgb(255,170,87);

color:rgb(52,128,184);

font-size:xx-small;

font-weight:bold;

}

.editor-button { width:18%;

padding:2px;

margin:4;

background-color:#9c0001;

border:2px solid black;

text-align:center;

font-weight:bold;

text-decoration:none;

color:white;

}

.editor-button:visited { color:#9c0001; }

.editor-button:active { color:white; }

.editor-button:hover { color:white; }

.link-title { margin-top:.5em; font-weight:bold }

.link-description { margin-left:2em; font-size:xx-small; }

p { margin-top:.5em;

margin-bottom:.5em;

}

pre { font-size:x-small;

background-color:#DFA894;

margin:1em;

}

table { border:none;

font-size:x-small;

}

td, th

{

border-right: medium none;

padding-right: 2px;

border-top: medium none;

padding-left: 2px;

padding-bottom: 2px;

margin: 2px;

border-left: medium none;

padding-top: 2px;

border-bottom: medium none;

background-color: ffffcc;

text-align: left;

}

th

{

background-color: 9EBBD9;

color: white;

}

ul, ol { margin-top:.5em;

}

h1

{

border-top: cccc99 1px solid;

margin-top: 1em;

padding-left: 4px;

font-size: medium;

margin-bottom: 0.5em;

border-left: cccc99 12px solid;

color: 993300;

background-color: ffffcc;

}

h2, h3, h4, h5, h6

{

margin-bottom: 0.5em;

color: 993300;

background-color: ffffcc;

}

h2 { font-size:small;

margin-top:1em;

border-left:8px solid cccc99;

border-top:1px solid cccc99;

padding-left:4px;

}

h3 { font-size:x-small;

margin-top:1em;

border-left:4px solid cccc99;

border-top:1px solid cccc99;

padding-left:4px;

}

h4 { font-size:x-small;

}

h5 { font-size:xx-small;

}

h6 { font-size:xx-small;

font-style:italic;

}

span.label {

font-weight:bold;

}

</style>

</head>

<body>

<h1>Xml Schema Code Generation Issue Report</h1>

<h2>Target Namespace = {<xsl:value-of select="xsd:schema/@targetNamespace"/>}</h2>

<xsl:apply-templates/>

</body>

</html>

</xsl:template>

<xsl:template match="xsd:choice">

<xsl:variable name="ElementCount">

<xsl:call-template name="GetElementCount"/>

</xsl:variable>

<xsl:variable name="NonElementCount">

<xsl:call-template name="GetNonElementCount"/>

</xsl:variable>

<xsl:variable name="SignificantNonElementCount">

<xsl:call-template name="GetSignificantNonElementCount"/>

</xsl:variable>

<xsl:variable name="HasChoiceCodeGenIssueRtf">

<xsl:call-template name="GetHasChoiceCodeGenIssue"/>

</xsl:variable>

<xsl:variable name="HasChoiceCodeGenIssue" select="$HasChoiceCodeGenIssueRtf = 'true'"/>

<xsl:variable name="BgColour">

<xsl:call-template name="GetBackgroundColour"/>

</xsl:variable>

<div style="Background-color:{$BgColour};">

<h2>Choice element with <xsl:if test="not($HasChoiceCodeGenIssue)">no </xsl:if>issue:</h2>

<xsl:call-template name="elementPath"/>

<br/>

Number of xsd:element children = <xsl:value-of select="$ElementCount"/>

<br/>

Number of non-xsd:element children = <xsl:value-of select="$NonElementCount"/>

<br/>

Number of significant non-xsd:element children = <xsl:value-of select="$SignificantNonElementCount"/>

<br/>

HasChoiceCodeGenIssue = <xsl:value-of select="$HasChoiceCodeGenIssue"/>

<br/>

Is HasChoiceCodeGenIssueRtf = 'true'? = <xsl:value-of select="$HasChoiceCodeGenIssueRtf = 'true'"/>

<br/>

Is HasChoiceCodeGenIssue = boolean(true)? = <xsl:value-of select="$HasChoiceCodeGenIssue"/>

<br/>

</div>

<xsl:apply-templates/>

</xsl:template>

<!-- Number of child xsd:element elements -->

<xsl:template name="GetElementCount">

<xsl:value-of select="count([name(.) = 'xsd:element'])"/>

</xsl:template>

<!-- Number of child non-xsd:element elements -->

<xsl:template name="GetNonElementCount">

<xsl:value-of select="count([name(.) != 'xsd:element'])"/>

</xsl:template>

<!-- Number of child significant non-xsd:element elements -->

<xsl:template name="GetSignificantNonElementCount">

<xsl:value-of select="count([name(.) != 'xsd:element' and name(.) != 'xsd:annotation'])"/>

</xsl:template>

<!-- Detects whether this choice may have a code generation issue -->

<xsl:template name="GetHasChoiceCodeGenIssue">

<xsl:variable name="ElementCount">

<xsl:call-template name="GetElementCount"/>

</xsl:variable>

<xsl:variable name="NonElementCount">

<xsl:call-template name="GetNonElementCount"/>

</xsl:variable>

<xsl:variable name="SignificantNonElementCount">

<xsl:call-template name="GetSignificantNonElementCount"/>

</xsl:variable>

<xsl:value-of select="boolean($ElementCount &gt; 0 and $SignificantNonElementCount &gt; 0)"/>

</xsl:template>

<xsl:template name="GetBackgroundColour">

<xsl:variable name="HasChoiceCodeGenIssueRtf">

<xsl:call-template name="GetHasChoiceCodeGenIssue"/>

</xsl:variable>

<xsl:variable name="HasChoiceCodeGenIssue" select="$HasChoiceCodeGenIssueRtf = 'true'"/>

<xsl:choose>

<xsl:when test="$HasChoiceCodeGenIssue">red</xsl:when>

<xsl:otherwise>lightgreen</xsl:otherwise>

</xsl:choose>

</xsl:template>

<xsl:template match="text()|@|">

<xsl:apply-templates/>

</xsl:template>

<!-- paths from elements -->

<xsl:template name="elementPath">

<xsl:for-each select="(ancestor-or-self::)">/<xsl:value-of select="name()"/>[<xsl:value-of select="1+count(preceding-sibling::)"/>]

<xsl:if test="@name">(name=<xsl:value-of select="@name"/>)</xsl:if>

<br/>

</xsl:for-each>

</xsl:template>

<!-- paths from attributes -->

<xsl:template name="attributePath">

<xsl:for-each select="parent::">

<xsl:call-template name="elementPath"/>

</xsl:for-each>

<xsl:text>/@</xsl:text>

<xsl:value-of select="name(.)"/>

</xsl:template>

</xsl:stylesheet>

1 Comment

  • Take a look at XsdObjGen - its much better at handling Schema constructs. For example, Xsd.exe seems to crash when it encounters a Schema enumeration element...

Comments have been disabled for this content.