[xsl] Elements that inherit children from other elements
Subject: [xsl] Elements that inherit children from other elements
From: Andreas Knote <andreas.knote@xxxxxxxxxxxxxx>
Date: Fri, 10 Dec 2010 11:23:21 +0100
|
Hello,
I am currently developing an XML Schema for a university course
catalogue. To ease maintenance, i thought of defining "module"s that
inherit some or all child-elements from another "module" (i call those
"derivedModule"). Any element that is not present inside of a
"derivedModule" should be copied from its
"baseModule" (of type "module", the one referred to by an XS:IDREF, not
a new type of element).
Right now, I use XS:ID and XS:IDREF to refer to a "module", and a
XSL-Template eventually combines the "derivedModule" with it's
"baseModule". It checks every child-element inside of a referred
"baseModule" for an occurence of the same element in "derivedModule" and
then copies either first or latter (if found).
I am not happy with this solution, as it feels wrong to have part of the
structural definition, the relation between a "derivedModule" and a
"module" (or it's children) as part of the stylesheet.
Now I am wondering whether it is actually possible to define such
relations within an XML Schema, or whether it is against the philosophy
behind XML.
I am thankful for any suggestions,
Andreas
----
Definiton for a "Module":
<xs:complexType name="ModulType"> <!-- Modul -->
<xs:sequence>
<xs:element maxOccurs="1" minOccurs="1" name="Name" type="xs:string"/>
<!-- Full name -->
<xs:element maxOccurs="1" minOccurs="1" name="Modulgruppe"
type="xs:string"/> <!-- Group for combination -->
....
<xs:element maxOccurs="1" minOccurs="1" name="Bemerkung"
type="FormatierterTextType"/> <!-- Annotation -->
</xs:sequence>
<xs:attribute name="id" type="xs:ID" use="required"/> <!-- ID -->
</xs:complexType>
Definition for a "derivedModule":
<xs:complexType name="AbgeleitetesModulType"> <!-- referring Module-->
<xs:sequence>
<xs:element name="Basismodul" maxOccurs="1" minOccurs="1"> <!-- ID of
baseModule to refer to-->
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:IDREF">
<xs:attribute name="wahl" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element maxOccurs="1" minOccurs="0" name="Name" type="xs:string"/>
<!--optional elements which overwrite those of the baseModule->
<xs:element maxOccurs="1" minOccurs="0" name="Modulgruppe"
type="xs:string"/>
....
<xs:element maxOccurs="1" minOccurs="0" name="Bemerkung"
type="FormatierterTextType"/>
</xs:sequence>
<xs:attribute name="id" type="xs:ID" use="required"/> <!-- new ID -->
XSL-Template to combine those two for further processing:
<xsl:template match="m:abgeleitetesModul">
<xsl:attribute name="id"><xsl:value-of select="./@id" /></xsl:attribute>
<xsl:variable name="basisID" select="m:Basismodul/text()" />
<xsl:variable name="abgModul" select="." />
<xsl:for-each
select="//m:Modulhandbuch/m:Studiengang/m:Modul[@id=$basisID]/*"> <!--
Look for elements in baseModul, then check for occurences in
derivedModule-->
<xsl:variable name="name" select="./local-name()" />
<xsl:choose>
<xsl:when test="$abgModul/*[name() = $name]">
<xsl:apply-templates select="$abgModul/*[local-name() = $name]"
mode="Inhalte" /> <!-- copy element from derivedModule -->
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="Inhalte" /> <!-- else copy element
from baseModule -->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>