XPathNavigator 如何尊重相对上下文?
How does XPathNavigator respect relative context?
简介:
如果我 运行 内部 XPath 查询,我得到与外部 XPath 查询的上下文无关的文本节点 (先前接收的节点)。这是否意味着 XPathNavigator 始终有整个树可用,因此它不考虑当前上下文?这是否意味着查询总是在根目录下执行?请看下面的例子:
这是book.xml的例子:
<bookstore>
<book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
<book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
<book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
<title>The Gorgias</title>
<author>
<name>Plato</name>
</author>
<price>9.99</price>
</book>
</bookstore>
XPath 查询:
- /bookstore/book/title
- /bookstore/book/author/first-name/text()
I would expect that If I run the second query (inner one) in the context of the
first one, I would not get any results. However I was wrong.
测试代码:
var xpath1 = "/bookstore/book/title";
var xpath2 = "/bookstore/book/author/first-name/text()";
var xDocument = new XPathDocument(new StreamReader("./book.xml"));
var navigator = xDocument.CreateNavigator();
navigator.MoveToChild(XPathNodeType.Element);
var iterator = navigator.Select(xpath1) as XPathNodeIterator;
while (iterator?.MoveNext() ?? false)
{
var result = iterator.Current.Evaluate(xpath2) as XPathNodeIterator;
while (result?.MoveNext() ?? false)
{
Console.WriteLine(result.Current.Value);
}
}
我得到的结果:
xpath1
returns 3个节点,resp.迭代器有 3 个元素,因为 <title>
显然在 XML 文档中出现了三次。然后我希望后续查询 xpath2
将 return 没有数据,因为我在 <title>
节点的上下文中。然而,似乎并非如此。在输出中我得到了 Benjamin Herman
.
的 3 倍
问题:
How did I get <first-name>
text values in the results even though I ran
the query in the context of the <title>
node? Does it mean that
XPathNavigator
always performs over the entire tree?
不,XPathNavigator
不会采用绝对 XPath,例如
/bookstore/book/author/first-name/text()
并相对应用。如果要在上下文节点为 title
时达到 author
等,则使用
../author/first-name/text()
或
following-sibling::author/first-name/text()
我更喜欢 xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication11
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("book")
.Where(x => (string)x.Element("title") == "The Autobiography of Benjamin Franklin")
.Select(x => new
{
author_first_name = (string)x.Descendants("first-name").FirstOrDefault(),
author_last_name = (string)x.Descendants("last-name").FirstOrDefault(),
price = (decimal)x.Element("price"),
genre = (string)x.Attribute("genre"),
publication = (DateTime)x.Attribute("publicationdate"),
isbn = (string)x.Attribute("ISBN")
}).ToList();
}
}
//------------------------------------------------------------------------------
}
简介:
如果我 运行 内部 XPath 查询,我得到与外部 XPath 查询的上下文无关的文本节点 (先前接收的节点)。这是否意味着 XPathNavigator 始终有整个树可用,因此它不考虑当前上下文?这是否意味着查询总是在根目录下执行?请看下面的例子:
这是book.xml的例子:
<bookstore>
<book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
<book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
<title>The Confidence Man</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
<book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
<title>The Gorgias</title>
<author>
<name>Plato</name>
</author>
<price>9.99</price>
</book>
</bookstore>
XPath 查询:
- /bookstore/book/title
- /bookstore/book/author/first-name/text()
I would expect that If I run the second query (inner one) in the context of the first one, I would not get any results. However I was wrong.
测试代码:
var xpath1 = "/bookstore/book/title";
var xpath2 = "/bookstore/book/author/first-name/text()";
var xDocument = new XPathDocument(new StreamReader("./book.xml"));
var navigator = xDocument.CreateNavigator();
navigator.MoveToChild(XPathNodeType.Element);
var iterator = navigator.Select(xpath1) as XPathNodeIterator;
while (iterator?.MoveNext() ?? false)
{
var result = iterator.Current.Evaluate(xpath2) as XPathNodeIterator;
while (result?.MoveNext() ?? false)
{
Console.WriteLine(result.Current.Value);
}
}
我得到的结果:
xpath1
returns 3个节点,resp.迭代器有 3 个元素,因为 <title>
显然在 XML 文档中出现了三次。然后我希望后续查询 xpath2
将 return 没有数据,因为我在 <title>
节点的上下文中。然而,似乎并非如此。在输出中我得到了 Benjamin Herman
.
问题:
How did I get
<first-name>
text values in the results even though I ran the query in the context of the<title>
node? Does it mean thatXPathNavigator
always performs over the entire tree?
不,XPathNavigator
不会采用绝对 XPath,例如
/bookstore/book/author/first-name/text()
并相对应用。如果要在上下文节点为 title
时达到 author
等,则使用
../author/first-name/text()
或
following-sibling::author/first-name/text()
我更喜欢 xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication11
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("book")
.Where(x => (string)x.Element("title") == "The Autobiography of Benjamin Franklin")
.Select(x => new
{
author_first_name = (string)x.Descendants("first-name").FirstOrDefault(),
author_last_name = (string)x.Descendants("last-name").FirstOrDefault(),
price = (decimal)x.Element("price"),
genre = (string)x.Attribute("genre"),
publication = (DateTime)x.Attribute("publicationdate"),
isbn = (string)x.Attribute("ISBN")
}).ToList();
}
}
//------------------------------------------------------------------------------
}