我正在使用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中)试图做一些事情:
xsi:nil = true
添加到空元素(注意它们必须没有子项,不仅没有文本,或者我的顶级节点被转换)答案 0 :(得分:0)
首先,名称空间声明不是属性,不能使用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)。
当然,最好的选择是什么都不做,因为正如你所指出的那样,差别纯粹是装饰性的。