XPathNavigator 可以 select 来自测试输入但不是真实输入
XPathNavigator can select from test input but not real input
这是我的 XML,通过将 serviceListXml
打印到控制台获得,如下面的代码所示:
<?xml version="1.0" encoding="utf-8"?>
<service xml:base="https://fnord/live/api/v1" xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
<workspace>
<atom:title type="text">Service List</atom:title>
<collection href="Erp.BO.ABCCodeSvc">
<atom:title type="text">Erp.BO.ABCCodeSvc</atom:title>
</collection>
<collection href="Erp.BO.AccountBudgetSvc">
<atom:title type="text">Erp.BO.AccountBudgetSvc</atom:title>
</collection>
<collection href="Erp.BO.ACTTypeSvc">
<atom:title type="text">Erp.BO.ACTTypeSvc</atom:title>
</collection>
<!-- hundreds more collection elements -->
</workspace>
</service>
这是我的代码:
var serviceListXml = client.GetStringAsync(serviceListUrl).GetAwaiter().GetResult();
//serviceListXml = "<foo><bar><collection/><collection/><collection/></bar></foo>";
Console.WriteLine(serviceListXml);
var doc = new XPathDocument(new StringReader(serviceListXml));
var nav = doc.CreateNavigator();
var foo = nav.Select("//collection");
Console.WriteLine("selected " + foo.Count + " elements");
这将选择 0 个元素。为什么?
如果我取消注释将 serviceListXml
设置为测试字符串的行,它会按预期找到 3 个元素。我以为我的真实 XML 上可能有 BOM,所以我尝试使用 serviceListXml.Substring(serviceListXml.IndexOf("<"))
,但没有任何区别。
这是因为在您的原始 XML 集合中位于 http://www.w3.org/2007/app
命名空间,这是 XML 的默认命名空间。为了能够 select collection
元素,你有两个选择:
选项 1: 将名称空间传递到您的 XPathDocument,例如:
var ns = new XmlNamespaceManager(nav.NameTable);
ns.AddNamespace("ns", "http://www.w3.org/2007/app");
var foo = nav.Select("//ns:collection", ns);
选项 2: 使用此 XPath:var foo = nav.Select("//*[local-name() = 'collection']");
这是我的 XML,通过将 serviceListXml
打印到控制台获得,如下面的代码所示:
<?xml version="1.0" encoding="utf-8"?>
<service xml:base="https://fnord/live/api/v1" xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
<workspace>
<atom:title type="text">Service List</atom:title>
<collection href="Erp.BO.ABCCodeSvc">
<atom:title type="text">Erp.BO.ABCCodeSvc</atom:title>
</collection>
<collection href="Erp.BO.AccountBudgetSvc">
<atom:title type="text">Erp.BO.AccountBudgetSvc</atom:title>
</collection>
<collection href="Erp.BO.ACTTypeSvc">
<atom:title type="text">Erp.BO.ACTTypeSvc</atom:title>
</collection>
<!-- hundreds more collection elements -->
</workspace>
</service>
这是我的代码:
var serviceListXml = client.GetStringAsync(serviceListUrl).GetAwaiter().GetResult();
//serviceListXml = "<foo><bar><collection/><collection/><collection/></bar></foo>";
Console.WriteLine(serviceListXml);
var doc = new XPathDocument(new StringReader(serviceListXml));
var nav = doc.CreateNavigator();
var foo = nav.Select("//collection");
Console.WriteLine("selected " + foo.Count + " elements");
这将选择 0 个元素。为什么?
如果我取消注释将 serviceListXml
设置为测试字符串的行,它会按预期找到 3 个元素。我以为我的真实 XML 上可能有 BOM,所以我尝试使用 serviceListXml.Substring(serviceListXml.IndexOf("<"))
,但没有任何区别。
这是因为在您的原始 XML 集合中位于 http://www.w3.org/2007/app
命名空间,这是 XML 的默认命名空间。为了能够 select collection
元素,你有两个选择:
选项 1: 将名称空间传递到您的 XPathDocument,例如:
var ns = new XmlNamespaceManager(nav.NameTable);
ns.AddNamespace("ns", "http://www.w3.org/2007/app");
var foo = nav.Select("//ns:collection", ns);
选项 2: 使用此 XPath:var foo = nav.Select("//*[local-name() = 'collection']");