|
next
|
 Subject: Mapping complex document with multiple xsd:type's defined Author: (Deleted User) Date: 23 Oct 2008 09:10 AM
|
Hi Boris,
this is an example of what I mean: suppose we have this XML document
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsi_type.xsd">
<item xsi:type="box">
<weight>10</weight>
</item>
<item xsi:type="package">
<shape>round</shape>
</item>
</root>
where a single 'item' element is used to represent different type of items, with xsi:type dynamically defining which one has to be used for validation.
The corresponding schema would then be
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="item" type="base"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="base" abstract="true"/>
<xsd:complexType name="box">
<xsd:complexContent>
<xsd:extension base="base">
<xsd:sequence>
<xsd:element name="weight" type="xsd:int"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="package">
<xsd:complexContent>
<xsd:extension base="base">
<xsd:sequence>
<xsd:element name="shape" type="xsd:string"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
so that 'item' is pointing to an abstract 'base', and 'box' and 'package' are two concrete types derived by it.
If we modify the schema to say
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="item" type="base"/>
<xsd:element name="dummybox" type="box" minOccurs="0"/>
<xsd:element name="dummypackage" type="package" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
so that XSLT mapper can know all the possible children of the 'root' element, we can do:
- create a new XSLT Stylesheet, without associating it to a source doc
- switch to mapper
- load the XSD in the source pane, and the desired target XML/XSD in the target pane
- insert an XSLT instruction 'apply-templates' and connect it to the root/item on the left and to the target element on the right
- in the text editor, move the xmlns:xsi declaration from the target element to the root xsl:stylesheet element, as we need it to be global
- right click on the 'dummybox' element and create a new template, using *[xsi:type='box'] as match expression
- mapper switches to the new template, so right click on the 'dummybox' and pick 'set as source context'
- right click on the target element, and pick 'set as target context'
- now drag a link between the 'weight' element to a child element of the target context
- create a new template also for the other type of 'item', with the same operations
- run the processing, and see that each 'item' was processed by a different template, using a different mapping created using drag & drop operations.
A sample XSL could be this one
<xsl:stylesheet version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<books>
<xsl:apply-templates select="root/item"/>
</books>
</xsl:template>
<xsl:template match="*[@xsi:type='box']">
<book>
<xsl:attribute name="pubdate">
<xsl:value-of select="weight"/>
</xsl:attribute>
</book>
</xsl:template>
<xsl:template match="*[@xsi:type='package']">
<magazine>
<xsl:attribute name="pubdate">
<xsl:value-of select="shape"/>
</xsl:attribute>
</magazine>
</xsl:template>
</xsl:stylesheet>
Hope this helps,
Alberto
|
|
|
|