[我正在尝试使用XPath选择具有Location
值的构面的项目,但是目前我什至尝试仅选择所有项目都失败了:系统愉快地报告它找到了0个项目,然后返回(相反,节点应通过foreach
循环进行处理)。非常感谢您提供帮助,无论是进行原始查询还是使XPath都能正常工作。
XML
<?xml version="1.0" encoding="UTF-8" ?>
<Collection Name="My Collection" SchemaVersion="1.0" xmlns="http://schemas.microsoft.com/collection/metadata/2009" xmlns:p="http://schemas.microsoft.com/livelabs/pivot/collection/2009" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<FacetCategories>
<FacetCategory Name="Current Address" Type="Location"/>
<FacetCategory Name="Previous Addresses" Type="Location" />
</FacetCategories>
<Items>
<Item Id="1" Name="John Doe">
<Facets>
<Facet Name="Current Address">
<Location Value="101 America Rd, A Dorm Rm 000, Chapel Hill, NC 27514" />
</Facet>
<Facet Name="Previous Addresses">
<Location Value="123 Anywhere Ln, Darien, CT 06820" />
<Location Value="000 Foobar Rd, Cary, NC 27519" />
</Facet>
</Facets>
</Item>
</Items>
</Collection>
C#
public void countItems(string fileName)
{
XmlDocument document = new XmlDocument();
document.Load(fileName);
XmlNode root = document.DocumentElement;
XmlNodeList xnl = root.SelectNodes("//Item");
Console.WriteLine(String.Format("Found {0} items" , xnl.Count));
}
该方法的功能远不止于此,但是既然可以执行所有操作,那么我假设问题就在这里。准确地调用root.ChildNodes
会返回FacetCategories
和Items
,所以我完全不知所措。
感谢您的帮助!
您的根元素具有名称空间。您需要添加一个名称空间解析器,并在查询中添加元素的前缀。
This article解释了解决方案。我已经修改了您的代码,使其获得1个结果。
public void countItems(string fileName)
{
XmlDocument document = new XmlDocument();
document.Load(fileName);
XmlNode root = document.DocumentElement;
// create ns manager
XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(document.NameTable);
xmlnsManager.AddNamespace("def", "http://schemas.microsoft.com/collection/metadata/2009");
// use ns manager
XmlNodeList xnl = root.SelectNodes("//def:Item", xmlnsManager);
Response.Write(String.Format("Found {0} items" , xnl.Count));
}
因为在根节点上有一个XML名称空间,所以在XML文档中没有“ Item”之类的东西,只有“ [namespace]:Item”,因此在使用XPath搜索节点时,需要指定命名空间。
如果您不喜欢,则可以使用local-name()函数来匹配其本地名称(前缀以外的名称部分)是您要查找的值的所有元素。它的语法有点丑陋,但是可以用。
XmlNodeList xnl = root.SelectNodes("//*[local-name()='Item']");