XML XSLT
This page documents how to store your data in a valid XML file so you can convert it in all the formats you need with the help of XSLT. The examples are for a small adress-list containing a name, the sex and a list of phonenumbers.
The Grammar
In order to define what structure our XML file should have, we need to define that.
XML Grammar via DTD
You can define the structure of an XML file via a Document Type Definition (DTD) file.
<!ELEMENT mylist (Person*)>
<!ELEMENT Person (Name, Geschlecht?, Telefon*)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Telefon (#PCDATA)>
<!ATTLIST Telefon
type CDATA #IMPLIED
>
Now we have an address-list for any number of persons (even putting nobody in there is allowed). One person consists of a Name, a sex (optional) and so much phone-numbers you like (even none). A phone-number can have a parameter called type. See also
- Selfhtml DTD (German)
XML Grammar via XSD
Defining the structure of an XML file via an XML Schema (XSD) file (which is an XML file, too) offers even more possibilities.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="mylist" type="MyContactsType" />
<xsd:complexType name="MyContactsType">
<xsd:sequence>
<xsd:element name="Person" type="PersonType" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="PersonType">
<xsd:element name="Name" type="xsd:string" maxOccurs="1" minOccurs="1"/>
<xsd:element name="Geschlecht" maxOccurs="1" minOccurs="1">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="F"></xsd:enumeration>
<xsd:enumeration value="M"></xsd:enumeration>
<xsd:enumeration value="?"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="Telefon" type="TelefonType" maxOccurs="unbounded" />
</xsd:complexType>
<xsd:complexType name="TelefonType">
<xsd:attribute name="type">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Mobile"></xsd:enumeration>
<xsd:enumeration value="Private"></xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>
</xsd:schema>
Write your XML file
Now it's time to write your data in an xml file. Remember to respect the Grammar you just defined.
<!DOCTYPE mylist SYSTEM "mylist.dtd">
<mylist>
<Person>
<Name>John Doe</Name>
<Geschlecht>M</Geschlecht>
<Telefon type="Mobil">555 123</Telefon>
<Telefon>555 647</Telefon>
</Person>
<Person>
<Name>Jane Doe</Name>
<Geschlecht>F</Geschlecht>
</Person>
</mylist>
See also:
Write a xsl file
<xsl:output method="text" /><xsl:template match="/">
<xsl:template match="/">
<xsl:for-each select="tgadressbuch/Person">
<xsl:sort select="Nachname"/>
<xsl:sort select="Vorname"/>
<xsl:apply-templates select="Nachname"/>
<xsl:apply-templates select="Vorname"/>
<xsl:apply-templates select="Telefonnummer"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This would go through the whole xml file and would output everything. But you don't need for-each for that:
<xsl:output method="text" /><xsl:template match="/">
<xsl:template match="/">
<xsl:apply-templates select="Person">
<xsl:sort select="Nachname"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Person">
<xsl:apply-templates select="Nachname"/>
<xsl:apply-templates select="Vorname"/>
<xsl:apply-templates select="Telefonnummer"/>
</xsl:template>
</xsl:stylesheet>
You can even have conditional parts:
<xsl:when test="Geschlecht='M'">
Frau!
</xsl:when>
<xsl:when test="Geschlecht='F'">
Mann!
</xsl:when>
<xsl:otherwise>
Keine Person.
</xsl:otherwise>
</xsl:choose>
Explain what elements you want to deal with:
<xsl:apply-templates select="Telefon[Telefon[(@type='Mobil')]">
Assemble an element with an attribute.
<xsl:attribute name = "href">
http://www.example.com
<xsl:apply-templates />
</xsl:attribute>
Ein Link
</xsl:element>
Change the characteristics of the output document
<xsl:output method="text" />
See also
- Selfthtml XSLT elements (German)
- XSL Transformations (XSLT)
- w3schools XSLT tutorial
- zvon.org XSLT tutorial
- XPath
- Extension to deal with dates and times
Use your xml and your xslt file to create a new file
e.g. with xsltproc:
Validate an xml file against an xml schema
Examples
Rename an element
Assume you have the following
</foo>
and want to rename it to
...
</bar>
Solution
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
is to write bar if you read foo. The trick is to use copy-of to keep the attributes.
Construct your own function
You can construct your own functions and even pass parameters to it. However, these parameters are nodesets an no normal string like parameters. So you can not add strings to such a parameter (at least not until now and not without further software modules).
<xsl:variable name="var2">//AAA/CCC/text()</xsl:variable>
<xsl:template match="/">
<xsl:call-template name="function">
<xsl:with-param name="var3" select="//FOO/BAR/" />
<xsl:with-param name="var4">//FOO/BAR/</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="function">
<xsl:param name="var3"/>
<xsl:param name="var4"/>
<xsl:value-of select="$var1"/>
<xsl:value-of select="$var2"/>
<xsl:value-of select="$var3"/>
<xsl:value-of select="$var4"/>
</xsl:template>
Modes
<xsl:apply-templates select="bar" mode="m1"/>
<xsl:apply-templates select="bar" mode="m2"/>
<xsl:apply-templates select="bar" mode="m3"/>
</xsl:template>
<xsl:template match="bar" mode="m1">
...
</xsl:template>
<xsl:template match="bar" mode="m2">
...
</xsl:template>
<xsl:template match="bar" mode="m3">
...
</xsl:template>
Match examples
<xsl:template match="foo[@bar='bar']">
<xsl:template match="foo[bar]" >