为 XDocument 指定默认命名空间给出空值

Specifiying a default namespace for XDocument gives empty value

当我尝试从文本中解析 XDocument 时,我可以获得这样的默认命名空间:

var xmlDocument1 = XDocument.Parse("<root xmlns='http://somenamespace'></root>");
var xmlNamespace1 = xmlDocument1.Root.GetDefaultNamespace().NamespaceName; // somenamespace

但是,如果我尝试手动创建 XDocument,我会得到一个空值:

var xmlRoot2 = new XElement(XName.Get("root", "http://somenamespace"));
var xmlDocument2 = new XDocument(xmlRoot2);
var xmlNamespace2 = xmlDocument2.Root.GetDefaultNamespace().NamespaceName; // is empty

我希望 xmlNamespace2 为“http://somenamespace”。我做错了什么吗?

编辑: 建议重复中的答案无法解决我的问题,即使我使用此处建议的功能也是如此: How to set the default XML namespace for an XDocument 我仍然会得到空的命名空间。这是链接问题的解决方案:

class Program
{
    static void Main(string[] args)
    {
        var xmlRoot = new XElement(XName.Get("root"));
        var xmlDocument = new XDocument(xmlRoot);
        SetDefaultXmlNamespace(xmlRoot, "http://somenamespace");
        var xmlNamespace = xmlDocument.Root.GetDefaultNamespace().NamespaceName; // is empty
    }

    public static void SetDefaultXmlNamespace(XElement xelem, XNamespace xmlns)
    {
        if (xelem.Name.NamespaceName == string.Empty)
            xelem.Name = xmlns + xelem.Name.LocalName;
        foreach (var e in xelem.Elements())
            SetDefaultXmlNamespace(e, xmlns);
    }
}

默认命名空间仍然是空的。

是的,这很棘手,因为即使字符串表示形式看起来不错,它仍然不起作用。

对于教育,添加:

var xml3 = xmlDocument2.ToString();
var xmlDocument3 = XDocument.Parse(xml3);            
var xmlNamespace3 = xmlDocument3.Root.GetDefaultNamespace().NamespaceName;

所以只有在您再次解析 xml 文本后,它才是您所期望的。

可能最短的方法:

var xmlRoot2 = new XElement(XName.Get("root", "http://somenamespace"), 
       new XAttribute("xmlns", "http://somenamespace"));

使用预定义的 XNameSpace.Xmlns 不适用于默认(无前缀)命名空间,因此只需 "xmlns" 即可。

我想我明白为什么我没有获得默认命名空间。根据MSDN:

When creating XML trees using C#, even if an XML tree would be serialized with a default namespace, if the namespace is not persisted in the XML tree as an attribute, this method will not report the namespace as the default namespace.

所以我可能需要显式设置 xmlns 属性:

class Program
{
    static void Main(string[] args)
    {
        var xmlRoot = new XElement(XName.Get("root", "http://somenamespace"));
        xmlRoot.SetAttributeValue("xmlns", "http://somenamespace");
        var xmlDocument = new XDocument(xmlRoot);
        var xmlNamespace = xmlDocument.Root.GetDefaultNamespace().NamespaceName;
    }
}

现在我得到了正确的命名空间名称。