Reputation: 1
I am trying to create an xsl-stylesheet that outputs my xml-contents in the correct order. Here is an example: XML:
...<p>This is<mark> a nested <b>text</b></mark></p>...
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<h2>
<xsl:value-of select="html/head/title"/>
</h2>
<div style="border:1px solid black;margin:30px;padding:30px;box-sizing:border-box;">
<xsl:for-each select="html/body/div[@class='toc']/table/tr/td/a">
<p><a>
<xsl:attribute name="href" namespace="uri">
<xsl:value-of select="current()/@href"/>
</xsl:attribute>
<xsl:value-of select="current()"/>
</a></p>
</xsl:for-each>
</div>
<xsl:for-each select="html/body/div[@class='chapter']">
<div style="border:1px solid black;margin:30px;padding:30px;box-sizing:border-box;">
<xsl:attribute name="id" namespace="uri"><xsl:value-of select ="current()/@id"/></xsl:attribute>
<p><xsl:value-of select ="current()/@id"/></p>
<xsl:call-template name="rec">
<xsl:with-param name="parents" select="current()"/>
</xsl:call-template>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template name="rec">
<xsl:param name="parents"></xsl:param>
<xsl:for-each select="$parents/*">
<xsl:if test="name() = 'img'">
<img class="{@class}" src="{@src}" style="max-width:100%;"/>
</xsl:if>
<xsl:if test="name() != 'img'">
<xsl:element name="{local-name()}">
<xsl:if test="name() != 'figure'">
<xsl:value-of select ="current()"/>
</xsl:if>
<xsl:call-template name="rec">
<xsl:with-param name="parents" select="current()"/>
</xsl:call-template>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This outputs:
This is a nested text
a nested text
text
What I am trying to get:
<p>This is<mark> a nested <b>text</b></mark></p>
I have tried just to include a CSS-Stylesheet (which would get rid of this particular problem), however this does not seem to work with images (e.g.), which won´t be displayed but will occure inside most documents.
The XSL-Stylesheet is supposed to be working with multiple documents (I wrote an exporter, that creates xml-files, that roughly follow the same syntax). The important part should only be the recursive function inside <xsl:template name="rec">
.
Help would be greatly appreciated. Thanks!
Upvotes: 0
Views: 186
Reputation: 167696
Basic push style, structure and order preserving processing usually relies on the identity transformation template plus custom templates for each node you need to transform e.g.
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="img">
<img class="{@class}" src="{@src}" style="max-width:100%;"/>
</xsl:template>
The duplicated text in your wrong output is created by the repeated use of xsl:value-of
in the recursive, named template. If you treat text as nodes and let any copying be handled through adequate templates, like the identity transformation template, you don't output text values several times.
Upvotes: 1