如何在指定的命名空间中输出属性

时间:2012-09-24 19:04:52

标签: xml xslt xml-namespaces

为什么下面的内容不能像我期望的那样工作?

<root xmlns:ns0="xmlns" 
      ns0:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:ns1="xsi" 
      ns1:schemaLocation="[some schema location]" />

基本上,我正在尝试将schemaLocation添加到没有这个的xml文件中: -

<xsl:template match="/s:*">
  <xsl:element name="{local-name()}" namespace="some other namespace">
    <xsl:attribute namespace="xmlns" name="xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute>
    <xsl:attribute namespace="xsi" name="schemaLocation">[some-loc]</xsl-attribute>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

和Xalan-C给出上面显示的xml。

我想要的是: -

<root xmlns:ns0="http://www.w3.org/2001/XMLSchema-instance"
      ns0:schemaLocation="[some schema location]" />

2 个答案:

答案 0 :(得分:3)

您需要<xsl:attribute name="xsi:schemaLocation">[some-loc]</xsl:attribute>

编辑(添加完整示例):

<?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:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
   <xsl:template match="root">
      <xsl:element name="{local-name()}" namespace="some other namespace">
         <!--<xsl:attribute namespace="xmlns" name="xsi">http://www.w3.org/2001/XMLSchema-instance</xsl:attribute>-->
         <xsl:attribute name="xsi:schemaLocation">[some-loc]</xsl:attribute>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:element>
   </xsl:template>
</xsl:stylesheet>

根据您的具体操作,您可以使用<xsl:copy>复制元素而不是<xsl:element name="{local-name()}"/>;它有点简单。

答案 1 :(得分:3)

当我解释你的问题并推断出你真正想要的是什么时,问题是你在namespace="..."中设置了一个你打算成为命名空间前缀的值,但是actually supposed to be 名称空间URI

因此,您可能想要的代码只是一个<xsl:attribute>元素:

<xsl:template match="/s:*">
  <xsl:element name="{local-name()}" namespace="some other namespace">
    <xsl:attribute namespace="http://www.w3.org/2001/XMLSchema-instance" 
        name="xsi:schemaLocation">[some-loc]</xsl-attribute>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

然后,XSLT处理器将在右侧命名空间中输出指定的schemaLocation属性,并且还将在需要时为其前缀发出名称空间声明(并且其前缀可能为xsi:,但不会必须是)。

这里的部分问题是,人们会在“命名空间”这个词(精神上或其他人)中徘徊,而不清楚他们的意思。命名空间不是命名空间前缀,也不是命名空间URI。命名空间通过其URI进行全局标识,通过其前缀进行本地标识。

如果XSLT规范将此属性命名为namespace-uri="..."而不是namespace="...",那么很少有人会陷入此陷阱。您还可以通过询问“namespace”是否真的意味着“名称空间URI”,“名称空间前缀”,“名称空间声明”等等来保护自己。