如何防止 .NET 的 XmlDocument 输出中出现空白 xmlns 属性?

Posted

技术标签:

【中文标题】如何防止 .NET 的 XmlDocument 输出中出现空白 xmlns 属性?【英文标题】:How to prevent blank xmlns attributes in output from .NET's XmlDocument? 【发布时间】:2010-09-13 04:41:48 【问题描述】:

在 .NET 中从 XmlDocument 生成 XML 时,第一次插入一个 没有 关联命名空间的元素时会出现一个空白的xmlns 属性;如何预防?

例子:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root",
    "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner"));
Console.WriteLine(xml.OuterXml);

输出:

<root xmlns="whatever:name-space-1.0"><loner xmlns="" /></root>

想要的输出:

<root xmlns="whatever:name-space-1.0"><loner /></root>

是否有适用于XmlDocument 代码的解决方案,而不是在 将文档转换为OuterXml 的字符串之后发生的事情?

我这样做的原因是看我是否可以使用 XmlDocument 生成的 XML 匹配特定协议的标准 XML。空白的xmlns 属性可能不会破坏或混淆解析器,但它也不存在于我所见过的该协议的任何用法中。

【问题讨论】:

【参考方案1】:

如果您的示例 XML 中的 &lt;loner&gt; 元素上没有 xmlns 默认命名空间声明,那么它将在 whatever:name-space-1.0 命名空间中,而不是在没有命名空间中。如果这是您想要的,您需要在该命名空间中创建元素:

xml.CreateElement("loner", "whatever:name-space-1.0")

如果您希望 &lt;loner&gt; 元素不在命名空间中,那么生成的 XML 正是您需要的,您不必担心自动为您添加的 xmlns 属性。

【讨论】:

问题在于不兼容的 XML 解析器(通常来自 Microsoft)无法处理 xmnls="")。 /.叫。他们希望回复他们随意抨击 MS 的评论。 @W. Craig Trader - 不能说我遇到过这个问题。例子? 正确,我不希望 节点具有命名空间,但我也不希望它具有空白命名空间属性 (xmlns)。我的推理只是看看我是否可以匹配这样设置的特定协议的 XML 输出。 这不是随意的抨击。 Microsoft 更新程序应用程序块使用 XML 清单来确定要交付给客户端的内容。不幸的是,Manifest 解析器无法处理 xmlns="";我必须编写一个后处理器来去除空的 xmlns 属性。【参考方案2】:

由于 root 位于无前缀命名空间中,任何想要取消命名空间的 root 子节点都必须像您的示例一样输出。解决方案是像这样为根元素添加前缀:

<w:root xmlns:w="whatever:name-space-1.0">
   <loner/>
</w:root>

代码:

XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement( "w", "root", "whatever:name-space-1.0" );
doc.AppendChild( root );
root.AppendChild( doc.CreateElement( "loner" ) );
Console.WriteLine(doc.OuterXml);

【讨论】:

谢谢,但是将命名空间添加到实际根目录会破坏与我正在使用的特定协议相关的 XML。 啊!我更了解你在说什么,并在写我自己的答案时考虑到了这一点。谢谢杰里米【参考方案3】:

如果可能,创建一个序列化类然后做:

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer serializer = new XmlSerializer(yourType);
serializer.Serialize(xmlTextWriter, someObject, ns);

这样更安全,如果你真的需要更多的控制,你可以用属性来控制命名空间。

【讨论】:

【参考方案4】:

感谢 Jeremy Lew 的回答和更多尝试,我想出了如何删除空白 xmlns 属性:在创建您希望 拥有的任何子节点时传入根节点的命名空间一个前缀。在根处使用没有前缀的命名空间意味着您需要在子元素上使用相同的命名空间,以便它们没有前缀。

固定代码:

XmlDocument xml = new XmlDocument();
xml.AppendChild(xml.CreateElement("root", "whatever:name-space-1.0"));
xml.DocumentElement.AppendChild(xml.CreateElement("loner", "whatever:name-space-1.0")); 
Console.WriteLine(xml.OuterXml);

感谢大家的所有回答,让我朝着正确的方向前进!

【讨论】:

没错。将 元素放在 "whatever:name-space-1.0" 命名空间中意味着空的 xmlns 属性(将其置于非命名空间中)在序列化时不会被添加到其中。如果您需要重新了解命名空间的工作方式,请查看 jclark.com/xml/xmlns.htm 注意:元素需要这个(或者可能更好的 doc.DocumentElement.NamespaceURI),但不要为 CreateAttribute() 指定命名空间,即使它是相同的 uri,你也会得到 xmlns:psomething .【参考方案5】:

我已经通过使用工厂模式解决了这个问题。我为 XElement 对象创建了一个工厂。作为工厂实例化的参数,我指定了一个 XNamespace 对象。因此,每次工厂创建 XElement 时,都会自动添加命名空间。这是工厂的代码:

internal class XElementFactory

    private readonly XNamespace currentNs;

    public XElementFactory(XNamespace ns)
    
        this.currentNs = ns;
    

    internal XElement CreateXElement(String name, params object[] content)
    
        return new XElement(currentNs + name, content);
    

【讨论】:

OP 询问的是XmlDocument,而不是XDocument【参考方案6】:

这是 JeniT 答案的变体(非常感谢您!)

XmlElement new_element = doc.CreateElement("Foo", doc.DocumentElement.NamespaceURI);

这消除了在任何地方复制或重复命名空间的麻烦。

【讨论】:

根据我的最佳反应。我们不必知道什么是文档默认命名空间(当我们不从头开始创建 xml 文件时很有用,即在读取和修改场景中)。【参考方案7】:

是的,您可以阻止 XMLNS 来自 XmlElement 。 第一次创建时间即将到来:就像那样

<trkpt lat="30.53597" lon="-97.753324" xmlns="">
    <ele>249.118774</ele>
    <time>2006-05-05T14:34:44Z</time>
</trkpt>

更改代码:并传递 xml 命名空间 像这样

C#代码:

XmlElement bookElement = xdoc.CreateElement("trkpt", "http://www.topografix.com/GPX/1/1");
bookElement.SetAttribute("lat", "30.53597");
bookElement.SetAttribute("lon", "97.753324");

【讨论】:

以上是关于如何防止 .NET 的 XmlDocument 输出中出现空白 xmlns 属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .NET 中使用 XmlWriter 创建 XmlDocument?

.NET XMLDocument.PreserveWhitespace:如何保留重要的空白?

XmlDocument 类正在删除格式、c#、.NET

如何在 c# .net CF 3.5 中使用 XmlDocument 向 xml 添加属性

.NET XmlDocument LoadXML 和实体

从 XmlDocument 到 XmlReader .Net