具有副本的XSLT和基本URI - 为什么uri会从XML文件更改为XSLT文件?

问题描述:

考虑下面的样式表具有副本的XSLT和基本URI - 为什么uri会从XML文件更改为XSLT文件?

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template name="start"> 
     <base-uris> 
      <node-base-uri> 
       <xsl:value-of select="base-uri(.)" /> 
      </node-base-uri> 
      <node-base-uri-from-copy> 
       <xsl:variable name="doc"> 
        <xsl:copy-of select="." /> 
       </xsl:variable> 
       <xsl:value-of select="base-uri($doc)" /> 
      </node-base-uri-from-copy> 
     </base-uris> 
    </xsl:template> 

</xsl:stylesheet> 

用下面的命令在命令行转化任意的XML文件与撒克逊人后:

java net.sf.saxon.Transform -s:xml/index.xml -xsl:xsl/base-uri.xsl -it:start 

我预料的一样值指向XML基础的URI源文件。但第二种情况下的基本URI(带有copy-of)指向XSLT文件。

<base-uris> 
    <node-base-uri>file:/xml/index.xml</node-base-uri> 
    <node-base-uri-from-copy>file:/xsl/base-uri.xsl</node-base-uri-from-copy> 
</base-uris> 

动机:在“现实世界中的样式表”我用一个模板中包含其他XML源。它们在源XML本身中指定(href属性中的相对路径)。

<xsl:template match="include" mode="includes"> 
    <xsl:copy-of select="document(@href, .)/*"/> 
</xsl:template> 

Spec

节点的基础URI被复制,除了在具有XML元素节点的情况下:base属性

我问题:

首先,我会l了解如何从XML文件保留/设置/复制基本URI,而不是从XSLT文件中复制基本URI。

其次,我不明白规范和/或不明白xml:base属性的东西。我只是想:我的代码中没有看到任何xml:base属性,所以应该复制节点的基本URI。

最后一句话:

玩的时候,我想出了这样的事情,感觉笨拙或干脆错误的方式去:

<node-base-uri-work-around> 
    <xsl:variable name="doc"> 
     <wrapper> 
      <xsl:attribute name="xml:base" select="base-uri(.)" /> 
      <xsl:copy-of select="." /> 
     </wrapper> 
    </xsl:variable> 
    <xsl:value-of select="base-uri($doc/wrapper)" /> 
</node-base-uri-work-around> 
+1

考虑准确地解释你正在做什么来运行转换,你只发布了带有命名模板的XSLT 3样式表,而没有显示任何输入XML,也没有解释如何运行转换,这对于理解并告诉你的输入来自哪里以及如何知道/确定基本URI。至于使用' xsl:variable>',为什么不简单使用''? –

+0

感谢Martin Honnen。只是在问题中提供了缺失的信息。是的,愚蠢的,为什么我只是不只是选择文件?现在它工作正常。 – Stefan

对于理解

  <xsl:variable name="doc"> 
       <xsl:copy-of select="." /> 
      </xsl:variable> 

查看https://www.w3.org/TR/xslt-30/#temporary-trees其中说:

的构建:

<xsl:variable name="tree"><a/></xsl:variable>

可视为的缩写:

<xsl:variable name="tree" as="document-node()"><xsl:document validation="preserve"><a/></xsl:document></xsl:variable>

,然后解释,“文档节点的基URI被取从样式表中变量绑定元素的基本URI。“。这就解释了为什么在这种情况下基URI是样式表URI。如果你想改变,你可以根据需要在xsl:variable绑定元素上使用​​。

我目前不确定<xsl:copy-of select="document(@href, .)/*"/>与您首先在您的问题中描述的问题有关,您将不得不详细说明在这种情况下您遇到基本URI问题的位置/方式。

+0

感谢Martin Honnen。这就是解释。一件小事,只是为了理解一切:'xsl:variable'的绑定元素是什么?它是''吗?如果是,则设置'xml:base'不会更改复制节点的基本URI。 – Stefan

+0

关于你评论的第二部分@Martin Honnen:''xsl:copy-of select =“document('some/rel/path/file.xml',。)/ *”/>'现在如预期的那样起作用。所以我现在完全高兴。也许我会发布这些天的另一个问题,关于在转换过程中可能包含额外的xml文件。 – Stefan

+0

规范说“文档节点的基本URI取自变量绑定元素的基本URI”,这意味着(隐式或显式)'xsl:document'的基本URI取自'xsl:variable' 。 –

我不知道如何解释“为什么?”的问题。一种解释是“在规范中哪里说这应该发生?”另一种解释是“规范的作者为什么决定让它按照这种方式行事?”

Martin Honnen指出了规范中指定使用xsl:variable创建为临时树的文档的基本URI的部分。至于为什么它是这样设计的:那么,历史上准确的答案就需要通过档案进行大量的拖网,即使这样也很困难,因为很多时候答案很简单,就是没有人提出任何替代方案。 XSLT 1.0表示每个节点都有一个基本URI,但据我所知,它没有说明构造节点的基本URI应该是什么;这是在XSLT 2.0中添加的。我不认为使用xsl:变量构造的文档节点的基本URI实际上可能不是样式表基本URI(此时没有其他东西真的可用),但5.7.1中的规则(构造复杂内容)规则10“复制元素或处理指令节点时,其基本URI属性将更改为与其新父项相同,除非它具有覆盖此属性的xml:base属性(请参阅[XML Base])。”当然可以用不同的方式写,我认为这个选择很有可能被辩论出来,但是到目前为止我还记得那些论点。这是坦率的一点,因为最终结果树的最可能的形式是序列化的XML或DOM,并且都不会保留节点的基本URI。

+0

谢谢你这个有趣的解释迈克尔凯。其实,我只是要求“规范中的哪些地方”和“请解释规范的这部分,我不明白”。作为XSLT的“初学者”,我无法对规范提出质疑。但在这个初学者层面上,我认为用xsl:copy-of/xsl:variable构造一个文档节点并保留/复制“源文档节点”中的基本URI也是多么直观。 – Stefan

+0

任何人如果对复杂而模糊的base-uri概念提出疑问,就会被取消参考资格作为“非常初学者”的资格;-) –