wie man Namespaces mit XPath ignoriert


111

Mein Ziel ist es, bestimmte Knoten mit XPath 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, dh mir unbekannt. Dann habe ich grundsätzlich 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. Holen Sie sich die untergeordneten Knoten des Dokuments und suchen Sie nach dem ersten Knoten mit einem Namespace-URI. Hoffen Sie, dass er dort ist, und verwenden Sie einfach den URI, in der Hoffnung, dass er der richtige ist. kann aus mehreren Gründen schief gehen

  3. Sag xpath irgendwie: "Schau, ich kümmere mich nicht um die Namespaces, finde einfach ALLE Knoten mit diesem Namen, ich kann dir sogar den Namen des Namespace sagen, nur nicht den URI". Und das ist die Frage hier ...

Dies ist keine Wiederholung zahlreicher Fragen, die hier oder hier zu finden sind: "Mein xpath-Ausdruck funktioniert nicht, weil mir die Namespace-Erkennung nicht bekannt ist ." Ich weiß, wie man Namespace-Awareness einsetzt. Nur nicht, wie man es loswird.


2
Wenn Sie die Schemata nicht kennen, woher wissen Sie, welche Elemente Sie möchten?
Paul Butcher


1
Danke, dass Sie darauf hingewiesen haben, Alejandro. Die Suche nach "Namespace xpath ignorieren" hätte diesen enthüllen sollen, aber nicht
kostja

2
@kostja: Nicht mit SO-Suchfeld suchen, es ist nutzlos ... Versuchen Sie es beim nächsten Mal mit Google. Tatsächlich wird dies vom SO-Team unterstützt.

1
Google Sitesearch macht es tatsächlich besser, nützliche Dinge auf SO zu finden. Ich frage mich, warum es nicht standardmäßig eine Option ist.
Nochmals vielen

Antworten:


164

Sie können die local-name()XPath-Funktion 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']

9
Sie können das auch verwenden local-name(), um auf Attribute zu verweisen, ohne den Namespace zu kennen, siehe: stackoverflow.com/q/21239181/274677
Marcus Junius Brutus


1
So einfach. hat meinen Nachmittag gerettet.
C Johnson


2

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;

Bei der Auswahl eines Knotens über XPath funktioniert dies. Leider können Sie das Dokument aufgrund eines 'The 'xmlns' attribute is bound to the reserved namespaceFehlers nicht speichern .
AutomatedChaos

2

Oder Sie können name () verwenden:

/path/to/*[name() = 'somenode']

Oder nur Suchattribute:

//*[@attribute="this one"]

Wenn Sie die XML-Datei als Powershell-Objekt öffnen, werden die Namespaces ignoriert:

[xml]$xml = get-content file.xml
$xml.path.to.somenode

0

Es ist mein Beispiel in Qt C ++. Qt unterstützt XPath 2.0:

    QString planePath = ":/Models/Plane.dae";
    QFile f(planePath);
    if (!f.open(QIODevice::ReadOnly))
    {
        std::cerr << "Failed to load the file: " <<
                     planePath.toStdString() << std::endl;
        return;
    }

    QXmlQuery query;
    query.bindVariable("myFile", &f);
//    query.setQuery("doc($myFile)//*[local-name() = 'p']/text()"); // it works too but it is XPath 1.0
    query.setQuery("doc($myFile)//*:p/text()");

    QString result;
    query.evaluateTo(&result);
    qDebug() << result;
    f.close();

Programmausgabe: "1 0 0 2 0 1 0 0 2 1 0 3 3 0 4 2 0 5\n"

Plane.dae

<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <asset>
    <contributor>
      <author>Blender User</author>
      <authoring_tool>Blender 2.83.3 commit date:2020-07-22, commit time:06:01, hash:353e5bd7493e</authoring_tool>
    </contributor>
    <created>2020-08-03T14:03:19</created>
    <modified>2020-08-03T14:03:19</modified>
    <unit name="meter" meter="1"/>
    <up_axis>Z_UP</up_axis>
  </asset>
  <library_effects>
    <effect id="PlaneMaterial-effect">
      <profile_COMMON>
        <technique sid="common">
          <lambert>
            <emission>
              <color sid="emission">0 0 0 1</color>
            </emission>
            <diffuse>
              <color sid="diffuse">0.01664001 0.8000001 0.01191879 1</color>
            </diffuse>
            <reflectivity>
              <float sid="specular">0.5</float>
            </reflectivity>
          </lambert>
        </technique>
      </profile_COMMON>
    </effect>
  </library_effects>
  <library_images/>
  <library_materials>
    <material id="PlaneMaterial-material" name="PlaneMaterial">
      <instance_effect url="#PlaneMaterial-effect"/>
    </material>
  </library_materials>
  <library_geometries>
    <geometry id="Plane-mesh" name="Plane">
      <mesh>
        <source id="Plane-mesh-positions">
          <float_array id="Plane-mesh-positions-array" count="12">-1 -1 0 1 -1 0 -1 1 0 1 1 0</float_array>
          <technique_common>
            <accessor source="#Plane-mesh-positions-array" count="4" stride="3">
              <param name="X" type="float"/>
              <param name="Y" type="float"/>
              <param name="Z" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <source id="Plane-mesh-normals">
          <float_array id="Plane-mesh-normals-array" count="3">0 0 1</float_array>
          <technique_common>
            <accessor source="#Plane-mesh-normals-array" count="1" stride="3">
              <param name="X" type="float"/>
              <param name="Y" type="float"/>
              <param name="Z" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <source id="Plane-mesh-map-0">
          <float_array id="Plane-mesh-map-0-array" count="12">1 0 0 1 0 0 1 0 1 1 0 1</float_array>
          <technique_common>
            <accessor source="#Plane-mesh-map-0-array" count="6" stride="2">
              <param name="S" type="float"/>
              <param name="T" type="float"/>
            </accessor>
          </technique_common>
        </source>
        <vertices id="Plane-mesh-vertices">
          <input semantic="POSITION" source="#Plane-mesh-positions"/>
        </vertices>
        <triangles material="PlaneMaterial-material" count="2">
          <input semantic="VERTEX" source="#Plane-mesh-vertices" offset="0"/>
          <input semantic="NORMAL" source="#Plane-mesh-normals" offset="1"/>
          <input semantic="TEXCOORD" source="#Plane-mesh-map-0" offset="2" set="0"/>
          <p>1 0 0 2 0 1 0 0 2 1 0 3 3 0 4 2 0 5</p>
        </triangles>
      </mesh>
    </geometry>
  </library_geometries>
  <library_visual_scenes>
    <visual_scene id="Scene" name="Scene">
      <node id="Plane" name="Plane" type="NODE">
        <matrix sid="transform">1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix>
        <instance_geometry url="#Plane-mesh" name="Plane">
          <bind_material>
            <technique_common>
              <instance_material symbol="PlaneMaterial-material" target="#PlaneMaterial-material">
                <bind_vertex_input semantic="UVMap" input_semantic="TEXCOORD" input_set="0"/>
              </instance_material>
            </technique_common>
          </bind_material>
        </instance_geometry>
      </node>
    </visual_scene>
  </library_visual_scenes>
  <scene>
    <instance_visual_scene url="#Scene"/>
  </scene>
</COLLADA>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.