问题 解析XDocument而不必继续指定默认命名空间


我有一些XML数据(类似于下面的示例),我想读取代码中的值。

为什么我被迫指定默认名称空间来访问每个元素?我原本期望默认命名空间用于所有元素。

有没有更合理的方法来实现我的目标?

示例XML:

<?xml version="1.0" encoding="UTF-8"?>
<ReceiptsBatch xmlns="http://www.secretsonline.gov.uk/secrets">
    <MessageHeader>
        <MessageID>00000173</MessageID>
        <Timestamp>2009-10-28T16:50:01</Timestamp>
        <MessageCheck>BX4f+RmNCVCsT5g</MessageCheck>
    </MessageHeader>
    <Receipts>
        <Receipt>
            <Status>OK</Status>
        </Receipt>
    </Receipts>
</ReceiptsBatch>

用于读取我之后的xml元素的代码:

XDocument xDoc = XDocument.Load( FileInPath );

XNamespace ns = "http://www.secretsonline.gov.uk/secrets";

XElement MessageCheck = xDoc.Element(ns+ "MessageHeader").Element(ns+"MessageCheck");
XElement MessageBody = xDoc.Element("Receipts");

11586
2017-09-12 11:20


起源

逻辑方法是为每个元素指定名称空间。只是因为你不必重复 xmlns 每个元素中的声明并不意味着子元素在默认命名空间中(xmlns="")。 - dtb
是否可以清除默认命名空间以节省我必须为每个元素名称添加“ns +”? - TeamWild


答案:


理论是文档的含义不受用户选择的名称空间前缀的影响。只要数据在命名空间中 http://www.secretsonline.gov.uk/secrets,作者是否选择使用前缀“s”,“secrets”,“_ x.cafe.babe”或“null”前缀(即使其成为默认命名空间)并不重要。您的应用程序不应该关心:它只是重要的URI。这就是您的应用程序必须指定URI的原因。


1
2017-09-12 14:15





如建议的那样 这个答案,您可以通过从文档的内存中副本中删除所有名称空间来完成此操作。我想只有在您知道结果文档中不会发生名称冲突时才应该这样做。

/// <summary>
/// Makes parsing easier by removing the need to specify namespaces for every element.
/// </summary>
private static void RemoveNamespaces(XDocument document)
{
    var elements = document.Descendants();
    elements.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
    foreach (var element in elements)
    {
        element.Name = element.Name.LocalName;

        var strippedAttributes =
            from originalAttribute in element.Attributes().ToArray()
            select (object)new XAttribute(originalAttribute.Name.LocalName, originalAttribute.Value);

        //Note that this also strips the attributes' line number information
        element.ReplaceAttributes(strippedAttributes.ToArray());
    }
}

5
2017-08-29 06:16



非常感谢!使简单的刮擦更容易 - Dirk Boer


您可以使用 XmlTextReader.Namespaces 读取XML文件时禁用名称空间的属性。

string filePath;
XmlTextReader xReader = new XmlTextReader(filePath);
xReader.Namespaces = false;
XDocument xDoc = XDocument.Load(xReader);

4
2017-11-28 12:48





这就是Linq-To-Xml的工作原理。如果它不在默认命名空间中,则找不到任何元素,并且它的后代也是如此。摆脱命名空间的最快方法是从初始XML中删除指向命名空间的链接。


2
2017-09-12 11:26



不是通过定义xmlns =“someNamespace”在XDocument中定义的默认命名空间。当您编写XML的文本版本时,您不必指定默认的ns,因此我不希望必须使用代码执行此操作。 - TeamWild


注意元素 Receipts 也在命名空间中 http://www.secretsonline.gov.uk/secrets, 所以 XNamespace 访问元素也需要:

XElement MessageBody = xDoc.Element(ns + "Receipts");

作为使用命名空间的替代方法,请注意您可以使用“命名空间不可知”xpath local-name() 和 namespace-uri(),例如

/*[local-name()='SomeElement' and namespace-uri()='somexmlns']

如果你省略了 namespace-uri 谓词:

/*[local-name()='SomeElement']

会匹配 ns1:SomeElement 和 ns2:SomeElement IMO我总是喜欢 XNamespace 在可能的情况下,名称空间不可知的xpath的用例非常有限,例如:用于解析具有未知模式的文档中的特定元素(例如,在服务总线内),或者尽可能地解析命名空间可以改变的文档(例如,未来校对,其中 xmlns 更改以匹配新版本的文档架构)


1
2017-09-12 11:28