You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-users@xalan.apache.org by John Nikolai <jn...@mac.com> on 2003/03/06 01:34:31 UTC
[Q] move common xslt to "template" file?
OK, I'm a bit new to Xalan and XSLT so the following may or may not be
the "proper" way to implement things. So if you see any glaring
problems, please let me know! =)
Basically I'm sorting an XML document (based on the date element) and
dumping the contents into another XML document using the same elements
and structure. Is this the best way to do sorting? We will have a
rather large (100 to 200 event elements) XML file to walk through and I
don't see any API in Xerces to sort a Document object...
I also have one more question which requires a look at the XML and XSL
documents.
I have the following XML document:
------
<?xml version="1.0" encoding="UTF-8"?>
<calendar>
<event>
<date>2003-03-26</date>
<name>BPC conference named event #-1186335162</name>
<type>BPC conference</type>
<theme>uh... theme???</theme>
<description>BPC conference helpful description...</description>
</event>
<event>
<date>2003-02-12</date>
<name>LEIP conference named event #-1992363215</name>
<type>LEIP conference</type>
<theme>uh... theme???</theme>
<description>LEIP conference helpful
description...</description>
</event>
</calendar>
------
and 2 different XSL documents:
-----
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml"
indent="yes"
xalan:indent-amount="4" />
<xsl:template match="/">
<calendar>
<xsl:apply-templates />
</calendar>
</xsl:template>
<xsl:template match="calendar">
<xsl:for-each select="event">
<xsl:choose>
<xsl:when test="number(substring(date,6,2)) > 2
and number(substring(date,9,2)) > 1
and number(substring(date,9,2)) < 5">
<event>
<date> <xsl:value-of select="date" /> </date>
<name> <xsl:value-of select="name" /> </name>
<type> <xsl:value-of select="type" /> </type>
<theme> <xsl:value-of select="theme" /> </theme>
<description> <xsl:value-of select="description" />
</description>
</event>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
-----
and ...
-----
<xsl:output method="xml"
indent="yes"
xalan:indent-amount="4" />
<xsl:template match="/">
<calendar>
<xsl:apply-templates />
</calendar>
</xsl:template>
<xsl:template match="calendar">
<xsl:for-each select="event">
<!-- <xsl:apply-templates> -->
<!-- substring(element, start_index, length) -->
<xsl:sort select="substring(date,1,4)"/> <!-- year -->
<xsl:sort select="substring(date,6,2)"/> <!-- month -->
<xsl:sort select="substring(date,9,2)"/> <!-- day -->
<event>
<date> <xsl:value-of select="date" /> </date>
<name> <xsl:value-of select="name" /> </name>
<type> <xsl:value-of select="type" /> </type>
<theme> <xsl:value-of select="theme" /> </theme>
<description> <xsl:value-of select="description" /> </description>
</event>
<!-- </xsl:apply-templates> -->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
-----
I get the output we want but was wondering if its possible to move this
code:
-----
<event>
<date> <xsl:value-of select="date" /> </date>
<name> <xsl:value-of select="name" /> </name>
<type> <xsl:value-of select="type" /> </type>
<theme> <xsl:value-of select="theme" /> </theme>
<description> <xsl:value-of select="description" /> </description>
</event>
-----
... into a template which could be imported to each of the XSL
documents as needed. I tried using <xsl:import> and <xsl:include>
thinking these were similar to the JSP counter parts but that's not the
case. The reason we want to does this is that if the XML document
changes we only want to update a single XSL document. Of course if the
date element name changes we would have to modify the XSL accordingly...
I know the following does not work but this gives you an idea of what
we want... Note that the only change is hte inclusion of "<xsl:import
href="event_xml_format.xsl" />"
-------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml"
indent="yes"
xalan:indent-amount="4" />
<xsl:template match="/">
<calendar>
<xsl:apply-templates />
</calendar>
</xsl:template>
<xsl:template match="calendar">
<xsl:for-each select="event">
<xsl:choose>
<xsl:when test="number(substring(date,6,2)) > 2
and number(substring(date,9,2)) > 1
and number(substring(date,9,2)) < 5">
<xsl:import href="event_xml_format.xsl" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
-------
Sorry for such a huge email...
Thanks much for your help!
- John
Re: [Q] move common xslt to "template" file?
Posted by Christophe Galerne <ch...@earthlink.net>.
Hi,
John Nikolai wrote:
> Basically I'm sorting an XML document (based on the date element) and
> dumping the contents into another XML document using the same elements
> and structure.
I think you are trying too hard. Dumping the contents of a XML document
is what <xsl:copy-of> is for.
Try this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml" indent="yes" xalan:indent-amount="4"/>
<xsl:template match="calendar">
<calendar>
<!-- also dump calendar attributes if any -->
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="event">
<xsl:sort select="date"/>
</xsl:apply-templates>
</calendar>
</xsl:template>
<xsl:template match="event">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
HTH,
Christophe
Re: [Q] move common xslt to "template" file?
Posted by kl...@attbi.com.
For your second question, to handle the
duplicated piece of <event>
...
</event>
elements, one way to handle this would be to
write a named template which spit out this set
of elements. Put this in the separate
stylesheet which gets included at the top of
the other two stylesheets (like a C header
file). Then use call-template to invoke this
at the correct spots. You may have to pass the
current node (.) as a parameter.