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

时间:2017-04-02 11:44:23

标签: xslt saxon

给出以下样式表

<?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>

使用以下命令从命令行使用Saxon转换任意XML文件后:

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

我期望指向XML源文件的基URI的值相同。但第二种情况下的基URI(带有副本)指向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属性

我的问题:

首先,我想知道,如何从XML文件而不是XSLT文件中保留/设置/复制基URI。

其次,我不了解Spec和/或不了解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>

2 个答案:

答案 0 :(得分:2)

至于理解

            <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。如果您想要更改它,可以根据需要在xml:base绑定元素上使用xsl:variable

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

答案 1 :(得分:2)

我不知道如何解释“为什么?”的问题。一种解释是“规范中的哪个位置会说这应该发生?”另一种解释是“为什么规范的作者决定让它以这种方式运行?”

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