C#XPath帮助 - 表达式不起作用

时间:2011-01-18 19:56:58

标签: c# xml xpath

以下是一个示例XML文档,它与我从中获取信息的文档相匹配:

<?xml version="1.0" standalone="yes"?>
<Products xmlns="http://tempuri.org/Products.xsd">
  <Movies>
    <Title>Title1</Title>
    <Language>English</Language>
  </Movies>
  <Movies>
    <Title>Title2</Title>
    <Language>English</Language>
  </Movies>
  <Movies>
    <Title>Title3</Title>
    <Language>French</Language>
  </Movies>
  <Books>
    <Title>BTitle1</Title>
    <Genre>Suspense</Genre>
  </Books>
  <Books>
    <Title>BTitle2</Title>
    <Genre>Suspense</Genre>
  </Books>
  <Books>
    <Title>BTitle3</Title>
    <Genre>SciFi</Genre>
  </Books>
  <Books>
    <Title>BTitle4</Title>
    <Genre>SciFi</Genre>
  </Books>
</Products>

这是我的代码,以获取所有具有悬疑类型的书籍:

//Get state list using XPath
XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file
XPathNavigator xNav = xDoc.CreateNavigator();
string booksQuery = "Books[Genre = \"Suspense\"]";
XPathNodeIterator xIter = xNav.Select(booksQuery);

while (xIter.MoveNext())
{
    //do stuff with xIter.Current
}

我尝试过多次查询,包括Products/Books[Genre = \"Suspense\"]Products/Books./BooksBooks。我的xIter始终没有任何项目。

我是XPath的新手,所以我确定这是一个非常简单的错误,但也许不是。我知道我可以使用myDataSet.ReadXml(myXmlPathString);从这个XML文件中获取带有[Movies]和[Books]表的DataSet,因此XML文件没有损坏。如果这有帮助。

所以,我的问题......我做错了什么?

4 个答案:

答案 0 :(得分:10)

XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file
XPathNavigator xNav = xDoc.CreateNavigator();
XmlNamespaceManager mngr = new XmlNamespaceManager(xNav.NameTable);
mngr.AddNamespace("p", "http://tempuri.org/Products.xsd");
string booksQuery = "//p:Books[p:Genre = \"Suspense\"]";
XPathNodeIterator xIter = xNav.Select(booksQuery,mngr);

答案 1 :(得分:6)

您正在寻找名为Books的元素,该元素不在命名空间中。 Products元素正在为该元素及其所有后代设置默认命名空间。您需要在XPath中使用命名空间...或使用不同的方法进行查询,例如LINQ to XML。 (我个人认为LINQ to XML 很多比XPath更容易处理 - 特别是当你需要涉及名称空间时。)

答案 2 :(得分:2)

正如乔恩所说,你错过了一个命名空间。

您可以在C#中执行以下操作

//Get state list using XPath
XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file
XPathNavigator xNav = xDoc.CreateNavigator();
XmlNamespaceManager xmlns = new XmlNamespaceManager(xNav.NameTable);
xmlns.AddNamespace("p", "http://tempuri.org/Products.xsd");
string booksQuery = "//p:Books[p:Genre = 'Suspense']";
XPathNodeIterator xIter = xNav.Select(booksQuery, xmlns);

while (xIter.MoveNext())
{
    //do stuff with xIter.Current
}

答案 3 :(得分:0)

使用VTD-XML,命名空间更简单...您可以选择是否忽略命名空间。

VTDGen vg = new VTDGen();
if(vg.parseFile("product.xml",true)){
  VTDNav vn = vg.getNav();
  AutoPilot ap = new AutoPilot(vn);
  ap.selectXPath("Produt[Genre='suspence']");
  int i = -1;
  while ((i = ap.evalXPath()) != -1)
  {
                    // processing logic
   }
}