14

我有一些 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");
4

5 回答 5

9

正如这个答案所建议的,您可以通过从文档的内存副本中删除所有命名空间来做到这一点。我想只有当您知道在生成的文档中不会有名称冲突时才应该这样做。

/// <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());
    }
}
于 2013-08-29T06:16:29.227 回答
6

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

string filePath;
XmlTextReader xReader = new XmlTextReader(filePath);
xReader.Namespaces = false;
XDocument xDoc = XDocument.Load(xReader);
于 2016-11-28T12:48:36.373 回答
3

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

于 2011-09-12T11:26:23.770 回答
1

请注意,该元素Receipts也在 namespace 中http://www.secretsonline.gov.uk/secrets,因此XNamespace访问该元素也需要:

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

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

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

如果省略namespace-uri谓词:

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

会匹配ns1:SomeElement等等ns2:SomeElement。IMO我总是希望XNamespace尽可能地使用,并且与名称空间无关的xpath的用例非常有限,例如用于解析具有未知模式的文档中的特定元素(例如在服务总线中),或者尽力而为解析命名空间可以更改的文档(例如,未来的校对,其中xmlns更改与文档模式的新版本匹配)

于 2011-09-12T11:28:40.433 回答
1

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

于 2011-09-12T14:15:40.557 回答