Reputation: 3
I need to do a transform on a number of XML files. To do the transforms I have a folder of various xsl stylesheets. I need to to the transform using a Java parser and I do not control the content of any of the stylesheets.
The stylesheets reference eachother with xsl:import
statements and they also include css style like so:
<style type="text/css">
<xsl:value-of select="document('../../common/display.css')" disable-output-escaping="yes"/>
</style>
Simplified example
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="../../common/functions.xsl"/>
<xsl:template match="/">
<html>
<head>
<title>..</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<style type="text/css">
<xsl:value-of select="document('../../common/display.css')" disable-output-escaping="yes"/>
</style>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I have managed to include all other xsl files by using the following stylesheet to do a first-pass processing.
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="xsl:include">
<xsl:copy-of select="document(@href)/xsl:stylesheet/*"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
However I cannot figure out how to do the same for the css references. Is it even possible to evaluate the xsl:value-of
to either get the value of the string within the call to document()
or otherwise get the content of the external css file?
Upvotes: 0
Views: 554
Reputation: 163322
Processing xsl:include
the way you are doing it isn't correct acccording to the XSLT specification, for a number of reasons: the copied instructions will have in-scope namespaces different from the original, they will have different values for controlling attributes such as version
and exclude-result-prefixes
, etc.
Handling xsl:import
this way is even more challenging, because of the need to respect import precedence. Basically, there are things you can do in a multi-module stylesheet that can't be done in a single-module stylesheet.
As for calls on document()
, to find the calls accurately you will need to parse all the XPath expressions. If the argument to document()
is a string literal, then in most cases it should be possible to generate a global variable containing the content of the referenced document, and replace the call on document()
by a reference to the variable. (But take care with base URIs).
You haven't actually said what you're trying to achieve by transforming your stylesheets in this way. It's a lot of effort, and I can't see what it accomplishes.
Upvotes: 1
Reputation: 1304
If you want access CSS files via XSLT stylesheet, use unparsed-text()
function instead of document()
function.
https://www.cw3.org/TR/2017/REC-xpath-functions-31-20170321/#func-unparsed-text
doument()
function assumes the target as XML file and returns the document-node. unparsed-text()
function treats the target as text file and returns the whole contents as xs:string
.
However you cannot use it XSLT version 1.0, instead yo should use XSLT 3.0 enabled processor such as Saxon HE.
Upvotes: 1