Frage

Ich habe einige XML-Daten (ähnlich dem folgenden Beispiel) und möchte die Werte im Code lesen.

Warum muss ich den Standard-Namespace angeben, um auf jedes Element zugreifen zu können?Ich hätte erwartet, dass der Standard-Namespace für alle Elemente verwendet wird.

Gibt es einen logischeren Weg, um mein Ziel zu erreichen?

XML-Beispiel:

<?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>

Code zum Lesen von XML-Elementen, nach denen ich suche:

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");

War es hilfreich?

Lösung

Die Theorie besagt, dass die Bedeutung des Dokuments nicht durch die Auswahl der Namespace-Präfixe durch den Benutzer beeinflusst wird.Solange sich die Daten im Namespace http://www.secretsonline.gov.uk/secrets spielt es keine Rolle, ob der Autor das Präfix "s", "Geheimnisse", "_x.cafe.babe" oder das Präfix "null" verwendet (dh es wird zum Standard-Namespace).Ihre Anwendung sollte sich nicht darum kümmern: Es kommt nur auf die URI an.Aus diesem Grund muss Ihre Anwendung den URI angeben.

Andere Tipps

Wie in dieser Antwort vorgeschlagen, können Sie dies tun, indem Sie alle Namespaces aus der In-Memory-Kopie des Dokuments entfernen.Ich nehme an, dies sollte nur durchgeführt werden, wenn Sie wissen, dass das resultierende Dokument keine Namenskollisionen enthält.

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

Sie können verwendenXmlTextReader.Namespaces -Eigenschaft zum Deaktivieren von Namespaces beim Lesen einer XML-Datei.

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

So funktioniert Linq-To-Xml.Sie können kein Element finden, wenn es sich nicht im Standard-Namespace befindet, und das Gleiche gilt für seine Nachkommen.Der schnellste Weg, um den Namespace zu entfernen, besteht darin, den Link zum Namespace aus Ihrem ursprünglichen XML zu entfernen.

Beachten Sie, dass sich das Element Receipts auch im Namespace http://www.secretsonline.gov.uk/secrets befindet, sodass der XNamespace auch für den Zugriff auf das Element erforderlich wäre:

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

Beachten Sie als Alternative zur Verwendung von Namespaces, dass Sie den "Namespace-agnostischen" xpath mithilfe von local-name() und namespace-uri() verwenden können, z. B.

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

Wenn Sie das Prädikat namespace-uri weglassen:

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

würde mit ns1:SomeElement und ns2:SomeElement usw. übereinstimmen. IMO Ich würde immer XNamespace bevorzugen, wenn dies möglich ist, und die Anwendungsfälle für namespace-agnostischen xpath sind ziemlich begrenzt, z.zum Parsen bestimmter Elemente in Dokumenten mit unbekannten Schemata (z. B. innerhalb eines Servicebusses) oder zum Best-Effort-Parsen von Dokumenten, bei denen sich der Namespace ändern kann (z. B. Zukunftssicherheit, bei der sich der generische Codetagcode ändert, um einer neuen Version des Dokumentschemas zu entsprechen)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top