【问题标题】:Is it possible to create an XmlElement with two xml namespaces?是否可以创建具有两个 xml 命名空间的 XmlElement?
【发布时间】:2020-02-10 08:33:07
【问题描述】:

我必须像下面这样生成 XML:

<foo:document xmlns="http://www.example.com/xmlns" xmlns:foo="http://www.example.com/xmlns/foo-version1">
    <foo:bar foo:baz="true" />
</foo:document>

如何在 c# 中使用System.Xml.XmlDocument 生成此文档?

【问题讨论】:

标签: c# xml xmldocument


【解决方案1】:

你可以这样做:

var fooNs = "http://www.example.com/xmlns/foo-version1";
var defNs = "http://www.example.com/xmlns";

var doc = new XmlDocument();

// Create and add the root element
var root = doc.CreateElement("foo", "document", fooNs);
doc.AppendChild(root);

// Add the default namespace (do note the root element is not in this namespace)
var defAttr = doc.CreateAttribute("xmlns");
defAttr.Value = defNs;
root.Attributes.Append(defAttr);

// Create the <foo:bar> element
var bar = doc.CreateElement("foo", "bar", fooNs);
var bazAttr = doc.CreateAttribute("foo", "baz", fooNs);
bazAttr.Value = XmlConvert.ToString(true);
bar.Attributes.Append(bazAttr);

// Add it to the root
root.AppendChild(bar);

注意事项:

  • 在命名空间中创建XmlElementXmlAttribute 节点时,始终首选使用带有前缀、localName 和命名空间URI 的Create() 重载:


    从语义的角度来看,真正重要的是节点本地名称和命名空间;前缀只是在范围内查找命名空间声明的查找。

  • 注意我没有明确添加xmlns:foo="http://www.example.com/xmlns/foo-version1" 属性?没有必要这样做,因为根元素是使用所需的命名空间和前缀通过doc.CreateElement("foo", "document", fooNs) 创建的。框架 (XmlWriter) 将在将 XmlDocument 写入 XML 时自动发出 xmlns:foo 属性。

    如果由于某种原因需要显式创建命名空间属性,可以按如下方式进行:

    // The following is redundant as the framework (XmlWriter) will add the necessary
    // xmlns:foo attribute as the XmlDocument is being written.  If you need to do it anway 
    // (e.g. to control the order) you can do it as follows.
    // (But note that XML attributes are unordered according to the XML specification, for details
    // see https://stackoverflow.com/questions/33746224/in-xml-is-the-attribute-order-important)
    var xmlnsNs = "http://www.w3.org/2000/xmlns/";
    
    var fooAttr = doc.CreateAttribute("xmlns", "foo", xmlnsNs);
    fooAttr.Value = fooNs;
    root.Attributes.Append(fooAttr);
    

演示小提琴 #1 here.

顺便说一句,正如用 cmets 编写的那样,使用 LINQ to XML 更容易做到这一点:

XNamespace fooNs = "http://www.example.com/xmlns/foo-version1";
XNamespace defNs = "http://www.example.com/xmlns";

var root = new XElement(fooNs + "document"
                        // Add the namespace declarations with your desired prefixes.  Be sure to pass them into the constructor.
                        , new XAttribute("xmlns", defNs.ToString())
                        , new XAttribute(XNamespace.Xmlns + "foo", fooNs.ToString())
                        // And add any required content.  The content can be passed into the constructor, or added later. 
                        , new XElement(fooNs + "bar", new XAttribute(fooNs + "baz", true)));

注意事项:

  • 使用 LINQ to XML,您永远无需担心 XElementXAttribute 的命名空间前缀。只需使用 XName 封装的正确命名空间和本地名称创建它们。框架 (XmlWriter) 将在写入时自动发出所有必要的命名空间属性。

    但如果您确实需要配置命名空间,您可以构造适当的XAttribute 对象,然后将它们传递给XElement constructor

  • 如需进一步阅读,请参阅How to: Create a Document with Namespaces (C#) (LINQ to XML)

演示小提琴#2 here.

【讨论】:

    【解决方案2】:

    Net 库希望默认命名空间(不带前缀)成为最后一个命名空间。我通常只使用限制较少的 Parse 方法。请参阅下面的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Linq;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                string xml = "<foo:document xmlns=\"http://www.example.com/xmlns\" xmlns:foo=\"http://www.example.com/xmlns/foo-version1\">" +
                             "   <foo:bar foo:baz=\"true\" />" +
                             "</foo:document>";
    
                XDocument doc = XDocument.Parse(xml);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 2010-10-06
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      相关资源
      最近更新 更多