Разбор 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");

5 ответов

Решение

Теория заключается в том, что значение документа не зависит от выбора пользователем префиксов пространства имен. Пока данные находятся в пространстве имен http://www.secretsonline.gov.uk/secrets, не имеет значения, решит ли автор использовать префикс "s", "секреты", "_x.cafe.babe". "или префикс" null "(то есть делает его пространством имен по умолчанию). Ваше приложение не должно заботиться: важен только URI. Вот почему ваше приложение должно указывать URI.

Как следует из этого ответа, вы можете сделать это, удалив все пространства имен из копии документа в памяти. Я полагаю, что это должно быть сделано только в том случае, если вы знаете, что в результирующем документе не будет конфликтов имен.

/// <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());
    }
}

Вы можете использовать свойство XmlTextReader.Namespaces, чтобы отключить пространства имен при чтении файла XML.

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

Вот как работает Linq-To-Xml. Вы не можете найти какой-либо элемент, если он не находится в пространстве имен по умолчанию, и то же самое верно и для его потомков. Самый быстрый способ избавиться от пространства имен - это удалить ссылку на пространство имен из вашего исходного XML.

Обратите внимание, что элемент 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 и т.д. ИМО я бы всегда предпочел XNamespace где это возможно, и варианты использования для независимого от пространства имен xpath весьма ограничены, например, для анализа определенных элементов в документах с неизвестными схемами (например, в служебной шине), или для анализа наилучших усилий, где пространство имен может измениться (например, будущее, где xmlns изменения в соответствии с новой версией схемы документа)

Другие вопросы по тегам