Let me start with an example and work my way to the question. Here is a very simple and clean XML data:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="flatdata.xsl"?>
<db>
<item>
<parent></parent>
<id>1</id>
<title>lorem ipsum</title>
</item>
<item>
<parent></parent>
<id>2</id>
<title>dolor sit amet</title>
</item>
<item>
<parent>1</parent>
<id>3</id>
<title>consectetur adipiscing elit.</title>
</item>
<item>
<parent>1</parent>
<id>4</id>
<title>Nunc varius tempus sem et fringilla</title>
</item>
<item>
<parent>2</parent>
<id>5</id>
<title>Aenean egestas</title>
</item>
<item>
<parent>2</parent>
<id>6</id>
<title>turpis vel placerat suscipit</title>
</item>
<item>
<parent>5</parent>
<id>7</id>
<title>ligula nulla consequat justo</title>
</item>
</db>
This is a flat database of items, with a tree structure lurking within, given by <parent>
relationship.
An XSLT that transforms this to a nested structure to reveal the tree-relationship of the item
s is pretty straightforward (I did my homework):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="db"/>
</body>
</html>
</xsl:template>
<xsl:template match="db">
<ul>
<xsl:apply-templates select="item[parent='']"/>
</ul>
</xsl:template>
<xsl:template match="item">
<xsl:variable name="vId" select="id"/>
<xsl:variable name="vChildren" select="../item[parent=$vId]"/>
<li>
<b><xsl:value-of select="concat(id,': ')"/></b> <xsl:value-of select="title"/>
<xsl:if test="$vChildren">
<ul>
<xsl:apply-templates select="$vChildren"/>
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
which yields the following output:
<ul>
<li>
<b>1: </b>lorem ipsum
<ul>
<li><b>3: </b>consectetur adipiscing elit.</li>
<li><b>4: </b>Nunc varius tempus sem et fringilla</li>
</ul>
</li>
<li>
<b>2: </b>dolor sit amet
<ul>
<li>
<b>5: </b>Aenean egestas
<ul>
<li>
<b>7: </b>ligula nulla consequat justo
</li>
</ul>
</li>
<li>
<b>6: </b>turpis vel placerat suscipit
</li>
</ul>
</li>
</ul>
The situation is that this nested (tree) structure is more convenient to process with XSLT for my purposes. I can use straightforward XPath etc to analyze which item
has how many descendants and so on. The XML data I receive from the source is flat, nothing I can do much about that.
So, how can one
I am trying to display the flatdata base results via XSLT on modern browsers, so I guess that means I am stuck with 1.0 (right?).
You can create a global variable <xsl:variable name="rtf"><xsl:apply-templates/></xsl:variable>
in any version of XSLT, however in XSLT 1.0 you would then have a result tree fragment which you can only output with xsl:copy-of
but not navigate with XPath unless you use an extension function like exsl:node-set
in <xsl:variable name="ns" select="exsl:node-set($rtf)" xmlns:exsl="http://exslt.org/common"/>
. However there is where inside browsers the trouble begins as IE and Edge don't support exsl:node-set
, only a proprietary msxsl:node-set
in a different namespace ( xmlns:msxsl="urn:schemas-microsoft-com:xslt"
). Using an extension function it is possible to trick IE into recognizing exsl:node-set
but that approach does not work in Edge. So in cross-browser XSLT 1.0 you are left with using xsl:choose/xsl:when/xsl:if
to test with eg function-available('exsl:node-set')
which function is supported to then convert the result tree fragment into a node set.
As an alternative you could look into Saxon-CE or Saxon-JS bringing XSLT 2.0 to browsers where the restriction about result tree fragments does not exist.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.