Reputation: 27486
I am transforming an XML file that needs to generate some elements based on the valid enumeration options defined in the XSD.
Suppose I have an XSD that declares a type and an element something like this:
<xs:simpleType name="optionType" nillable="true">
<xs:restriction base="xs:string">
<xs:maxLength value="50"/>
<xs:enumeration value="USERCHOICE">
</xs:enumeration>
<xs:enumeration value="DEFAULT">
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
...
<xs:element name="chosenOption" type='optionType'/>
...
<xs:element name="availableOption" type='optionType'/>
The input will only contain the chosen option, so you can imagine it looks like this:
<options>
<chosenOption>USERCHOICE</chosenOption>
</options>
I need to have an output that looks like this:
<options>
<chosenOption>USERCHOICE</chosenOption> <!-- This comes from incoming XML -->
<!-- This must be a list of ALL possible values for this element, as defined in XSD -->
<availableOptions>
<availableOption>USERCHOICE</availableOption>
<availableOption>DEFAULT</availableOption>
</availableOptions>
</options>
Is there a way to have the XSL extract the enumeration values USERCHOICE
and DEFAULT
from the XSD and produce them in the output?
This will run on WebSphere 6 and will be used by an XSLT 1.0 engine. :(
(The schema file does not change often but it will change now and then and I'd rather only have to update the schema file instead of update the schema file and XSLT)
Upvotes: 4
Views: 4686
Reputation: 27994
Here's a prototype that assumes that your input XML and XSD are as simple as the samples above. To be tweaked according to ways in which they may vary. If you need help with that tweaking, let me know.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:variable name="xsd" select="document('mySchema.xsd')"/>
<xsl:template match="/options">
<xsl:copy>
<xsl:for-each select="*">
<xsl:variable name="eltName" select="local-name()"/>
<xsl:copy-of select="." />
<availableOptions>
<xsl:variable name="optionType"
select="$xsd//xs:element[@name = $eltName]/@type"/>
<xsl:apply-templates
select="$xsd//xs:simpleType[@name = $optionType]/
xs:restriction/xs:enumeration"/>
</availableOptions>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="xs:enumeration">
<availableOption><xsl:value-of select="@value" /></availableOption>
</xsl:template>
</xsl:stylesheet>
Upvotes: 5