我有一个生成XSL的代码,其中包含多个XSL文件。包含文件以调用模板。可能存在我的文件中不存在我需要包含的文件之一的情况。当原始文件丢失时,我可以创建一个具有相同名称和空模板的虚拟文件,但是当原始文件存在时,我会收到重复错误。
贝娄就是一个例子:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:date="java.util.Date"
xmlns:vector="java.util.Vector"
xmlns:math="java.lang.Math"
xmlns:int="java.lang.Integer"
xmlns:saxon="http://saxon.sf.net/"
extension-element-prefixes="date vector math int saxon">
<xsl:include href="file_for_template1.xsl"/> <!-- MIGHT NOT EXIST -->
<xsl:include href="file_for_template2.xsl"/> <!-- MIGHT NOT EXIST -->
<xsl:include href="file_for_template3.xsl"/> <!-- MIGHT NOT EXIST -->
<xsl:output method="xml"
version="1.0"
encoding="UTF-8"
indent="yes"/>
<xsl:variable name="path"
select="concat(base-uri(//Test),'.temp')"/>
<xsl:template match="/">
<xsl:result-document href="file:/{$path}" method="xml">
<!-- create the root node -->
<TEST_GENERATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="test.xsd">
<xsl:element name="TEST_ELEMENT">
<!-- SHOULD NOT BE CALLED IF THE FILE DOES NOT EXIST -->
<xsl:call-template name="template1Call"/>
<!-- SHOULD NOT BE CALLED IF THE FILE DOES NOT EXIST -->
<xsl:call-template name="template2Call"/>
<!-- SHOULD NOT BE CALLED IF THE FILE DOES NOT EXIST -->
<xsl:call-template name="template3Call"/>
</xsl:element>
<!-- end of root node -->
</TEST_GENERATION>
<!-- end of document -->
</xsl:result-document>
</xsl:template>
答案 0 :(得分:3)
我希望您告诉我们更多关于您要解决的问题,而不是关注您所选择的方法遇到的困难。如果我们知道真正的要求,我们或许可以提出更好的解决方法。
use-when属性允许您使用此类编译时控件,使您能够根据外部条件选择性地排除样式表的各个部分(包括xsl:import / include声明)。你可以尝试:
<xsl:import href="module1.xsl"
use-when="doc-available('module1.xsl')"/>
XSLT 2.0表示在评估use-when表达式的上下文中没有可用的文档,因此这将始终返回false,但此规则在XSLT 3.0中更改。在3.0中,您还可以传递一个静态参数来说明xsl:import是否应该处于活动状态,并在use-when属性中引用静态参数。
您的下一个问题是,如果已排除导入,则调用模板指令将失败,除非您执行某些操作以取消激活这些指令。一种解决方案是用函数调用替换它们,您可以通过function-available()
上的测试有条件地排除它。
但是我对帮助你走这条路感到不安,这就是为什么我之前没有回答这个问题。我想我可能会带你进入沼泽地,如果我们知道你的真实目的地,我们或许可以建议一条比你正在使用的更好的路线。
答案 1 :(得分:1)
以下是我将与catalogs一起使用的方法(作为背景信息,目录是可以帮助提供依赖于配置文件的实体解析器的文件,以便可以根据符号名称有效地解析实体 - 除其他可能性外):
在输入样式表中,您可以通过以下方式修改导入:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:date="java.util.Date"
xmlns:vector="java.util.Vector"
xmlns:math="java.lang.Math"
xmlns:int="java.lang.Integer"
xmlns:saxon="http://saxon.sf.net/"
extension-element-prefixes="date vector math int saxon">
<xsl:include href="cfg:module:file_for_template1.xsl"/> <!-- MIGHT NOT EXIST -->
<xsl:include href="cfg:module:file_for_template2.xsl"/> <!-- MIGHT NOT EXIST -->
<xsl:include href="cfg:module:file_for_template3.xsl"/> <!-- MIGHT NOT EXIST -->
...
</xsl:stylesheet>
对文件的引用已更改为符号名称 - 引用的文件本身不存在。
这是目录中的内容。您需要首先设置这样的目录,以便您能够加载一个真实的&#34;目前,文件只指向虚拟(默认)模板文件。
<?xml version="1.0" encoding="UTF-8"?>
<catalog prefer="system" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<uri name="cfg:module:file_for_template1.xsl" uri="path/to/default/file_for_template1.xsl"/>
<uri name="cfg:module:file_for_template2.xsl" uri="path/to/default/file_for_template2.xsl"/>
<uri name="cfg:module:file_for_template3.xsl" uri="path/to/default/file_for_template3.xsl"/>
</catalog>
Saxon documentation - Using XML catalogs将为您提供有关如何指定XSL-T引擎使用的目录的信息。
现在,当您需要使用模块中定义的模板文件覆盖模板文件时,您将为模块设置目录以及重新定义的模板文件,几乎相同的条目除外uri
属性(在目录中)将指向模块中的模板文件。我假设从生成XSL的代码中,您还可以创建适当的目录。
在调用转换时,您将提供目录列表(以分号分隔)。在这里,您通常会首先输入&#34;标准&#34;目录,然后&#34;模块&#34;目录(顺序很重要)。当在目录中多次找到相同的条目时,最新的获胜。因此,如果模块目录重新定义名称&#34; cfg:module:file_for_template1.xsl
&#34;所以它指向模块文件,这个文件将被加载。
注意:使用目录时,文件路径是相对于XML目录解析的。