在创建新的 XmlElement 并设置 InnerXml 后出现空白 xmlns=""。

3
我遇到了一个类似的问题:
除此之外,我创建了一个新节点,然后将它的InnerXml属性设置为XML字符串。
参考链接:.NET的XmlDocument如何防止输出中出现空xmlns属性?
    Dim ns As String = "http://test"
    Dim doc As XmlDocument = New XmlDocument
    doc.LoadXml(String.Format("<data xmlns=""{0}""></data>", ns))

    Dim newElement As XmlElement = doc.CreateElement("new", ns)
    newElement.InnerXml = "<person><name>Joe</name></person>"

    Dim result As String = newElement.OuterXml

我期望的是:
<data xmlns="http://test">
  <new>
    <person>
      <name>Joe</name>
    </person>
  </new>
</data>

它实际创建的是:
<data xmlns="http://test">
  <new>
    <person xmlns="">
      <name>Joe</name>
    </person>
  </new>
</data>

根据MSDN,解析是在当前命名空间上下文中完成的。我原以为当前命名空间上下文不仅适用于newElement,还适用于所有导入的子节点。我使用CreateDocumentFragment()时也遇到了同样的问题。
是否有任何方法可以防止在导入XML字符串时,立即在newElement下的子节点中显示空命名空间?
1个回答

4

这句话的意思是:

解析将在当前命名空间上下文中完成。

也就是说,您的XML字符串可能包含的任何命名空间前缀都将以文档定义的命名空间前缀的上下文中进行解释。

这样可以使以下内容工作:

Const ns As String = "http://test"
Const ns_foo As String = "http://www.example.com"

Dim doc As XmlDocument = New XmlDocument()
doc.LoadXml(String.Format("<data xmlns=""{0}"" xmlns:foo=""{1}""></data>", ns, ns_foo))

Dim newElement As XmlElement = doc.CreateElement("new", ns)
doc.DocumentElement.AppendChild(newElement)

newElement.InnerXml = "<foo:person><foo:name>Joe</foo:name></foo:person>"

并导致
<data xmlns:foo="http://www.example.com" xmlns="http://test">
   <new>
      <foo:person>
         <foo:name>Joe</foo:name>
      </foo:person>
   </new>
</data>

然而,没有前缀的节点根据定义不属于特定的命名空间。它们属于默认命名空间

当设置InnerXml时,您无法影响默认命名空间。它总是被认为是"空"命名空间。


1
这正是我的观点。没有前缀的节点不属于任何特定的命名空间,它们将位于默认命名空间中。那么为什么我的 innerxml <person><name>Joe</name></person> 会变成 <person xmlns=""> <name>Joe</name></person>?它不应该省略 xmlns="" 并假定根节点提供的 xmlns 吗? - HashTagDevDude
1
是的,但默认命名空间不是“目标文档所具有的任何内容”,而是“在将字符串解析为节点时可以合理假设的任何内容”。而且你不能合理地假设新节点应该始终获得与其父节点相同的默认命名空间 - 部分原因是这对于“另一半”用例来说是错误的,部分原因是这会使向文档添加“无命名空间”的节点变得不可能。 - Tomalak
2
解析文档时,默认命名空间最初为空命名空间。当元素设置 xmlns="foo" 时,该元素的命名空间及其所有后代的默认命名空间将为 "foo" - 直到该元素结束或其后代之一使用自己的 xmlns 覆盖它。InnerXml 有点特殊,因为在调用它时,主文档的解析已经结束。因此,一个新的解析会话开始,并且不能对默认命名空间做出任何假设,因此它从空命名空间开始。 - Tomalak
2
感谢您清晰的解释。我现在完全理解它为什么能够工作了。 - HashTagDevDude
1
@ChrisArbogast 不建议使用搜索和替换来处理XML字符串,但删除 xmlns = "" 几乎不会有任何破坏性风险,除非它实际上应该存在于某些节点上。SetInnerXml() 也是一种懒惰的方法 - 如果您正在生成XML,则可以使用DOM方法生成节点,如果您从其他地方获取XML,则可以将其解析为临时文档,然后使用 .ImportNode() 将其导入到主文档中。 - Tomalak
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接