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. <?
<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 > 0 and $SignificantNonElementCount > 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>