管理包含在XSL中

时间:2016-04-04 10:19:58

标签: xslt xslt-2.0

我有一个生成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>

2 个答案:

答案 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一起使用的方法(作为背景信息,目录是可以帮助提供依赖于配置文件的实体解析器的文件,以便可以根据符号名称有效地解析实体 - 除其他可能性外):

  1. 在输入样式表中,您可以通过以下方式修改导入:

    <?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>
    
  2. 对文件的引用已更改为符号名称 - 引用的文件本身不存在。

    1. 这是目录中的内容。您需要首先设置这样的目录,以便您能够加载一个真实的&#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>
      
    2. Saxon documentation - Using XML catalogs将为您提供有关如何指定XSL-T引擎使用的目录的信息。

      1. 现在,当您需要使用模块中定义的模板文件覆盖模板文件时,您将为模块设置目录以及重新定义的模板文件,几乎相同的条目除外uri属性(在目录中)将指向模块中的模板文件。我假设从生成XSL的代码中,您还可以创建适当的目录。

      2. 在调用转换时,您将提供目录列表(以分号分隔)。在这里,您通常会首先输入&#34;标准&#34;目录,然后&#34;模块&#34;目录(顺序很重要)。当在目录中多次找到相同的条目时,最新的获胜。因此,如果模块目录重新定义名称&#34; cfg:module:file_for_template1.xsl &#34;所以它指向模块文件,这个文件将被加载。

      3. 注意:使用目录时,文件路径是相对于XML目录解析的。