xml 如何使用 XPath 忽略命名空间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4440451/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 13:26:25  来源:igfitidea点击:

how to ignore namespaces with XPath

xmlxpathnamespacesxml-namespaces

提问by kostja

My goal is to extract certain nodes from multiple xml files with multiple namespaces using XPath. Everything works fine as long as i know the namespace URIs. The namespace name itself remains constant, but the Schemas (XSD) are sometimes client-generated i.e. unknown to me. Then i am left with basically three choices :

我的目标是使用 XPath 从具有多个命名空间的多个 xml 文件中提取某些节点。只要我知道命名空间 URI,一切都可以正常工作。命名空间名称本身保持不变,但架构 (XSD) 有时是客户端生成的,即我不知道。然后我基本上剩下三个选择:

  1. use just one schema for the namespace, hoping nothing goes wrong (can i be sure?)

  2. get the children nodes of the document and look for the first node with a namespace URI, hoping its there and just use the URI , hoping its the correct one. can go wrong for multiple reasons

  3. somehow tell xpath : "look, i dont care about the namespaces, just find ALL nodes with this name, i can even tell you the name of the namespace, just not the URI". And this is the question here...

  1. 仅对命名空间使用一种模式,希望不会出错(我可以确定吗?)

  2. 获取文档的子节点并查找具有命名空间 URI 的第一个节点,希望它在那里,然后只使用 URI ,希望它是正确的。可能会因为多种原因出错

  3. 以某种方式告诉 xpath :“看,我不关心名称空间,只需找到具有此名称的所有节点,我什至可以告诉您名称空间的名称,而不是 URI”。这是这里的问题......

This is not a reiteration of numerous "my xpath expression doesnt work because i am not aware of namespace awareness" questions as found hereor here. I know how to use namespace awareness. Just not how to get rid of it.

这不是在此处此处找到的众多“我的 xpath 表达式不起作用,因为我不知道名称空间意识”问题的重复。我知道如何使用命名空间意识。只是不知道如何摆脱它。

回答by Dirk Vollmar

You can use the local-name()XPath function. Instead of selecting a node like

您可以使用local-name()XPath 函数。而不是选择一个节点

/path/to/x:somenode

you can select all nodes and filter for the one with the correct local name:

您可以选择所有节点并筛选具有正确本地名称的节点:

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

回答by Andrés Cuadros Suárez

You can do the same In XPath2.0in a less verbose syntax:

您可以在XPath2.0中以更简洁的语法执行相同的操作:

/path/to/*:somenode

回答by Pierre Vonderscher

You could use Namespace = false on a XmlTextReader

您可以在 XmlTextReader 上使用 Namespace = false

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

with :

和 :

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;

回答by js2010

Or you can use name():

或者你可以使用 name():

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

Or only search attributes:

或者只搜索属性:

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

If you open the xml as a powershell object, it ignores the namespaces:

如果您将 xml 作为 powershell 对象打开,它将忽略命名空间:

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