Ответ 1
Вы можете использовать функцию local-name()
XPath. Вместо того, чтобы выбрать node как
/path/to/x:somenode
вы можете выбрать все узлы и фильтр для одного с правильным локальным именем:
/path/to/*[local-name() = 'somenode']
Моя цель - извлечь определенные узлы из нескольких XML файлов с несколькими пространствами имен, используя XPath. Все работает нормально, пока я знаю URI пространства имен. Само имя пространства имен остается постоянным, но схемы (XSD) иногда генерируются клиентом, то есть неизвестны мне. Затем я остаюсь в основном тремя вариантами:
используйте только одну схему для пространства имен, надеясь, что ничего не получится (я могу быть уверен?)
получить дочерние узлы документа и искать первый node с URI пространства имен, надеясь, что он там, и просто использовать URI, надеясь, что он правильный. может пойти не так по нескольким причинам
как-то сказать xpath: "Посмотрите, я не забочусь о пространствах имен, просто найдите ВСЕ узлы с этим именем, я даже могу назвать имя пространства имен, а не URI". И вот тут вопрос...
Это не повторение многочисленных "мое выражение xpath не работает, потому что я не осведомлен об осознании пространства имен", как найдено здесь или . Я знаю, как использовать понимание пространства имен. Просто не как избавиться от него.
Вы можете использовать функцию local-name()
XPath. Вместо того, чтобы выбрать node как
/path/to/x:somenode
вы можете выбрать все узлы и фильтр для одного с правильным локальным именем:
/path/to/*[local-name() = 'somenode']
Вы можете сделать то же самое в XPath2.0 в менее подробном синтаксисе:
/path/to/*:somenode
Вы можете использовать Namespace = false в 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");
}
с помощью:
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;
Мне не разрешено комментировать (!!), поэтому я могу просто позволить им заткнуть меня или в любом случае добавить свои два цента с помощью "ответа на комментарий"...
Я обнаружил, что у этого хака есть еще один недостаток: он не работает, если документ объявляет какие-либо префиксы пространства имен XML (двоеточие недопустимо в именах XML, а при использовании пространств имен == false читатель интерпретирует двоеточие как часть имени) например
<ParentTag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://anyNamespace.com">