how to ignore namespaces with XPath

2019-01-05 10:17发布

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 :

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

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

3条回答
在下西门庆
2楼-- · 2019-01-05 10:48

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

/path/to/*:somenode
查看更多
3楼-- · 2019-01-05 10:53

You could use Namespace = false on a 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");
}

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;
查看更多
姐就是有狂的资本
4楼-- · 2019-01-05 11:01

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

/path/to/x:somenode

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

/path/to/*[local-name() = 'somenode']
查看更多
登录 后发表回答