有没有办法在循环或递归中使用SelectSingleNode来获得相同的结果 Select方法返回的节点集?我不想用的原因 选择是因为在执行时我无法显示进度消息 用户。此外,如果需要很长时间,那么应用程序可能会出现 已停止响应,用户可能认为它已挂断。如果我可以使用 反复选择SelectSingleNode,然后我可以显示进度并保留应用程序 resposive。我需要这个来处理用户可能输入的任何XPath表达式。 在第一个SelectSingleNode之后,我认为xpath表达式必须是 改变,所以起点是当前的背景,我无法弄明白。
string localXPathExpr = "//b:book[contains(b:author,'Melville')]";
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.XmlResolver = null;
XmlReader reader = null;
XmlNamespaceManager nsmgr=null;
XPathNavigator nav = null;
XPathNodeIterator xNode = null;
reader = XmlReader.Create(xmlfile, settings);
nsmgr = new XmlNamespaceManager(reader.NameTable);
//if xpath has prefix, extract it and add to namespacemanager
string prefix = Form1.NSPrefix(localXPathExpr);
if (string.IsNullOrEmpty(prefix) == false)
{
if (string.IsNullOrEmpty(Form1.NSUri) == false)
{
nsmgr.AddNamespace(prefix, Form1.NSUri);
}
else
{
nsmgr.AddNamespace(prefix, rootNodeNamespace);
}
} XPathDocument doc = new XPathDocument(reader);
nav = doc.CreateNavigator();
// xNode = nav.Select(localXPathExpr, nsmgr);
XPathNavigator single = nav.SelectSingleNode(localXPathExpr, nsmgr);
//to get the next book, I think the xpath expression would have to be changed so the start point is the current context of single
// I tried the current context operator "./b:book[contains(b:author,'Melville')]" and also tried
// "/b:book[contains(b:author,'Melville')]" but they both return null.
XPathNavigator next = single.SelectSingleNode(localXPathExpr, nsmgr);
输入来源:
<bookstore xmlns="http://www.mybookstore.com/books">
<book genre="novel" publicationdate="1847-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="novel" publicationdate="1841-09-11" ISBN="0-201-76361-2">
<title>Moby Dick</title>
<author>
<first-name>Herman</first-name>
<last-name>Melville</last-name>
</author>
<price>11.99</price>
</book>
</bookstore>
答案 0 :(得分:1)
答案是:是的,但是......
有几个问题需要解决:
0.1。 如果XML文件很大,我怀疑大量处理时间不是用于评估XPath表达式本身,而是用于解析XML文件。
0.2。 始终尽量避免使用//
缩写,因为它通常会导致评估速度非常慢。如果您知道XML文档的结构并且b:book
仅出现在某些位置,那么使用它会更有效(例如):
/*/b:book[contains(b:author,'Melville')]
大于
//b:book[contains(b:author,'Melville')]
0.3。 仅在你无法做到的情况下.2。上面,您可以实现以下:
在循环SelectSingleNode()
中调用以下表达式(索引应该是循环计数器):
(//b:book[contains(b:author,'Melville')])[1]
(//b:book[contains(b:author,'Melville')])[2]
(//b:book[contains(b:author,'Melville')])[3]
(//b:book[contains(b:author,'Melville')])[4]
。 。 。 。 。 。 。 。 。 。 。 。 。
假设优化器很好并且在找到想要的出现时停止评估完整表达式,那么对第一个表达式的评估将比评估完整表达式//b:book[contains(b:author,'Melville')]
快得多。
当然,选择最后一个节点的时间仍然很长,因此您可以采用混合策略:逐个选择前N个(比如100个)节点,然后评估完整表达式{{1} }。
答案 1 :(得分:0)
我无法使用SelectSingleNode
看到任何明确的解决方案。
我建议你使用完整的Select
和BackgroundWorker
帖子让你的表单在选择过程中做出响应(当然这样可以防止显示选择的进度)。
BTW,我认为xpath查询的缓慢是由contains
部分引起的。
所以,作为一种解决方法,你可以这样做:
contains
(您的选择应该明显加快)contains
的节点。在此循环中,您可以显示进度条... 答案 2 :(得分:0)
我认为你应该调查大部分时间占用的东西。解析XPathDocument
很可能是最耗时的部分。您可以通过扩展XmlTextReader
类在解析过程中提供反馈。一个非常简单的例子:
public class MyXmlReader : XmlTextReader
{
public MyXmlReader(string filename)
: base(filename)
{
}
public override bool Read()
{
Console.WriteLine("Reading line {0}.", this.LineNumber);
return base.Read();
}
}
答案 3 :(得分:0)