Domanda

Dispongo di alcuni dati XML (simili all'esempio seguente) e desidero leggere i valori nel codice.

Perché sono costretto a specificare lo spazio dei nomi predefinito per accedere a ogni elemento?Mi sarei aspettato che lo spazio dei nomi predefinito fosse utilizzato per tutti gli elementi.

Esiste un modo più logico per raggiungere il mio obiettivo?

XML di esempio:

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

Codice per leggere gli elementi xml che cerco:

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");
È stato utile?

Soluzione

La teoria è che il significato del documento non è influenzato dalla scelta dell'utente dei prefissi dello spazio dei nomi.Finché i dati si trovano nello spazio dei nomi http://www.secretsonline.gov.uk/secrets, non importa se l'autore sceglie di utilizzare il prefisso "s", "secrets", "_x.cafe.babe" o il prefisso "null" (ovvero, rendendolo lo spazio dei nomi predefinito).Alla tua applicazione non dovrebbe interessare: è solo l'URI che conta.Ecco perché la tua applicazione deve specificare l'URI.

Altri suggerimenti

Come suggerito da questa risposta , puoi farlo rimuovendo tutti gli spazi dei nomi dalla copia in memoria del documento.Suppongo che questo dovrebbe essere fatto solo se sai che non ci saranno collisioni di nomi nel documento risultante.

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

Puoi utilizzare XmlTextReader.Namespaces per disabilitare gli spazi dei nomi durante la lettura del file XML.

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

Ecco come funziona Linq-To-Xml.Non è possibile trovare alcun elemento, se non è nello spazio dei nomi predefinito, e lo stesso vale per i suoi discendenti.Il modo più veloce per sbarazzarsi dello spazio dei nomi è rimuovere il collegamento allo spazio dei nomi dal tuo XML iniziale.

Nota che l'elemento Receipts è anche nello spazio dei nomi http://www.secretsonline.gov.uk/secrets, quindi per l'accesso all'elemento sarebbe richiesto anche il XNamespace:

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

In alternativa all'utilizzo degli spazi dei nomi, tieni presente che puoi utilizzare xpath "agnostico dello spazio dei nomi" utilizzando local-name() e namespace-uri(), ad esempio

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

Se ometti il predicato namespace-uri:

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

Corrisponde a ns1:SomeElement e ns2:SomeElement ecc. IMO Preferirei sempre XNamespace ove possibile, e i casi d'uso per xpath indipendente dallo spazio dei nomi sono piuttosto limitati, ad es.per l'analisi di elementi specifici in documenti con schemi sconosciuti (ad esempio all'interno di un bus di servizio), o per l'analisi di documenti in cui lo spazio dei nomi può cambiare (ad esempio, verifica futura, dove il xmlns cambia per corrispondere a una nuova versione dello schema del documento)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top