bagaimana mengabaikan ruang nama dengan XPath

111

Tujuan saya adalah mengekstrak node tertentu dari beberapa file xml dengan beberapa ruang nama menggunakan XPath. Semuanya berfungsi dengan baik selama saya tahu URI namespace. Nama namespace itu sendiri tetap konstan, tetapi Skema (XSD) kadang-kadang dihasilkan klien, yaitu tidak saya ketahui. Kemudian pada dasarnya saya memiliki tiga pilihan:

  1. gunakan hanya satu skema untuk namespace, berharap tidak ada yang salah (dapatkah saya yakin?)

  2. dapatkan node turunan dari dokumen dan cari node pertama dengan URI namespace, berharap ada di sana dan cukup gunakan URI, berharap node tersebut benar. bisa salah karena berbagai alasan

  3. entah bagaimana memberitahu xpath: "lihat, saya tidak peduli tentang namespace, cukup temukan SEMUA node dengan nama ini, saya bahkan dapat memberi tahu Anda nama namespace, hanya saja URI". Dan inilah pertanyaannya di sini ...

Ini bukan pengulangan dari banyak pertanyaan "ekspresi xpath saya tidak berfungsi karena saya tidak mengetahui kesadaran ruang nama" seperti yang ditemukan di sini atau di sini . Saya tahu bagaimana menggunakan kesadaran namespace. Hanya saja tidak bagaimana menyingkirkannya.

kostja
sumber
2
Jika Anda tidak tahu skema, bagaimana Anda tahu elemen apa yang Anda inginkan?
Paul Butcher
4
Duplikat persis dari Cara mengabaikan namespace saat
1
terima kasih telah menunjukkannya, Alejandro. Pencarian untuk "abaikan namespace xpath" seharusnya mengungkapkan yang ini, tapi tidak
kostja
2
@kostja: Jangan cari dengan kotak pencarian SO, percuma ... Coba Google lain kali. Faktanya, hal ini didorong oleh tim SO.
1
Pencarian situs Google sebenarnya melakukan pekerjaan yang lebih baik dalam menemukan hal-hal yang berguna di SO. Saya bertanya-tanya mengapa ini bukan opsi per default. Terima kasih sekali lagi, Alejandro
kostja

Jawaban:

164

Anda dapat menggunakan local-name()fungsi XPath. Alih-alih memilih simpul seperti

/path/to/x:somenode

Anda dapat memilih semua node dan memfilter yang memiliki nama lokal yang benar:

/path/to/*[local-name() = 'somenode']
Dirk Vollmar
sumber
9
Anda juga dapat menggunakan local-name()untuk merujuk ke atribut juga, dengan cara namespace-tidak sadar, lihat: stackoverflow.com/q/21239181/274677
Marcus Junius Brutus
1
Sangat sederhana. menyelamatkan sore saya.
C Johnson
21

Anda dapat melakukan hal yang sama di XPath2.0 dengan sintaks yang tidak terlalu bertele-tele:

/path/to/*:somenode
Andrés Cuadros Suárez
sumber
2

Anda bisa menggunakan Namespace = false pada XmlTextReader

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

dengan:

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;
Pierre Vonderscher
sumber
Untuk memilih node melalui XPath, ini berfungsi; Sayangnya Anda tidak dapat menyimpan dokumen karena 'The 'xmlns' attribute is bound to the reserved namespacekesalahan.
AutomatedChaos
2

Atau Anda dapat menggunakan name ():

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

Atau hanya cari atribut:

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

Jika Anda membuka xml sebagai objek PowerShell, itu mengabaikan ruang nama:

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

Ini adalah contoh saya di Qt C ++. Qt mendukung 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();

Keluaran program: "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>
8 Pengamat 8
sumber