【问题标题】:Add namespace to root node when root node may have multiple types当根节点可能有多种类型时,将命名空间添加到根节点
【发布时间】:2016-11-14 15:50:46
【问题描述】:

我正在使用 XLST 1.0 并想Transform XML to add 'nil' attributes to empty elements。我发现命名空间被添加到每个匹配的元素中,例如我的输出看起来像: <age xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />

我知道这是有效的,但我宁愿将它添加到我的顶级节点。我遇到了这个答案:How can I add namespaces to the root element of my XML using XSLT?

但是我有多个可能的根节点,所以我想我可以这样做:

  <xsl:template match="animals | people | things">
    <xsl:element name="{name()}">
      <xsl:attribute name="xmlns:xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

但是我从 Visual Studio 中得到一个错误“prexix xmlns not defined”,我不知道该怎么做。

Here is my total XLST file(由于某种原因它不会粘贴到 SO)它试图做一些事情:

  1. 将不同类型的动物转化为单一类型
  2. 将命名空间添加到根节点
  3. xsi:nil = true 添加到空元素(注意它们必须没有子元素,而不仅仅是没有文本,否则我的顶级节点会被转换)

【问题讨论】:

标签: xml xslt xslt-1.0


【解决方案1】:

首先,命名空间声明不是属性,不能使用xsl:attribute 指令创建。

您可以使用xsl:copy-of 在所需位置“手动”插入命名空间声明,例如:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="/*">
    <xsl:copy>
        <xsl:copy-of select="document('')/xsl:stylesheet/namespace::xsi"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[not(node())]">
    <xsl:copy>
        <xsl:attribute name="xsi:nil">true</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

但是,结果相当依赖于处理器。例如,Xalan 将忽略此指令,并像以前一样在它输出的每个空节点处重复声明。通常,您几乎无法控制 XSLT 处理器如何序列化输出。

另一种选择是在根级别实际使用命名空间声明,例如:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="/*">
    <xsl:copy>
        <xsl:attribute name="xsi:nil">false</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*[not(node())]">
    <xsl:copy>
        <xsl:attribute name="xsi:nil">true</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

这适用于我测试过的所有处理器 (YMMV)。

当然,最好的选择是什么都不做,因为正如您所指出的,差异纯粹是表面上的。

【讨论】:

    猜你喜欢
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2015-04-14
    相关资源
    最近更新 更多