web-dev-qa-db-de.com

wie man Namespaces mit XPath ignoriert

Mein Ziel ist es, mithilfe von XPath bestimmte Knoten aus mehreren XML-Dateien mit mehreren Namespaces zu extrahieren. Alles funktioniert gut, solange ich die Namespace-URIs kenne. Der Namespace-Name selbst bleibt konstant, aber die Schemas (XSD) werden manchmal vom Client generiert, d. H. Mir unbekannt. Dann habe ich drei Möglichkeiten:

  1. verwenden Sie nur ein Schema für den Namespace und hoffen Sie, dass nichts schief geht (kann ich sicher sein?)

  2. rufen Sie die untergeordneten Knoten des Dokuments ab und suchen Sie nach dem ersten Knoten mit einem Namespace-URI. Hoffen Sie, dass er dort ist, und verwenden Sie einfach den URI, und hoffen Sie, dass er der richtige ist. kann aus mehreren Gründen schief gehen

  3. sage xpath irgendwie: "sieh mal, ich interessiere mich nicht für die Namespaces, finde einfach ALLE Nodes mit diesem Namen, ich kann dir sogar den Namen des Namespaces sagen, nur nicht den URI". Und das ist die Frage hier ...

Dies ist keine Wiederholung zahlreicher Fragen wie hier oder hier "Mein xpath-Ausdruck funktioniert nicht, da mir das Namespace-Bewusstsein nicht bekannt ist". Ich kann Namespace-Bewusstsein verwenden. Nur nicht, wie man es los wird.

93
kostja

Sie können die Funktion local-name() XPath verwenden. Anstatt einen Knoten wie auszuwählen

/path/to/x:somenode

sie können alle Knoten auswählen und nach dem mit dem richtigen lokalen Namen filtern:

/path/to/*[local-name() = 'somenode']
140
Dirk Vollmar

Sie können dasselbe in XPath2. in einer weniger ausführlichen Syntax tun:

/path/to/*:somenode

Sie können Namespace = false für einen XmlTextReader verwenden

[TestMethod]
public void MyTestMethod()
{
    string _withXmlns = @"<?xml version=""1.0"" encoding=""utf-8""?>
<ParentTag xmlns=""http://anyNamespace.com"">
<Identification value=""ID123456"" />
</ParentTag>
";

    var xmlReader = new XmlTextReader(new MemoryStream(Encoding.Default.GetBytes(_withXmlns)));

    xmlReader.Namespaces = false;

    var content = XElement.Load(xmlReader);

    XElement elem = content.XPathSelectElement("/Identification");

    elem.Should().NotBeNull();
    elem.Attribute("value").Value.Should().Be("ID123456");
}

mit:

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
1

Ich darf nicht kommentieren (!!), also könnte ich mich einfach zum Schweigen bringen lassen oder meine zwei Cent trotzdem mit einer "Kommentarantwort" hinzufügen ...

Ich habe festgestellt, dass dieser Hack ein weiteres Manko hat: Es funktioniert nicht, wenn das Dokument XML-Namespace-Präfixe deklariert (Doppelpunkt ist in XML-Namen nicht zulässig und bei Namespaces == false interpretiert der Leser den Doppelpunkt als Teil des Namens). , z.B.

<ParentTag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xmlns="http://anyNamespace.com">
0
Dojo