XPathExpression AddSort fails

本文关键字:fails AddSort XPathExpression | 更新日期: 2023-09-27 18:11:50

我试图从xpath查询排序结果,但它失败了。

Ooutput:

ABC
DEF

但我期待:

DEF
ABC

源代码是这样的,它使用XML表达式并对结果进行排序:

var doc = new XPathDocument("testmsg2.xml");
var nav = doc.CreateNavigator();
const string query = "//Z/X/Code";
var expr = nav.Compile(query);
expr.AddSort("Code",
             XmlSortOrder.Descending,
             XmlCaseOrder.None,
             "",
             XmlDataType.Text);
switch (expr.ReturnType)
{                
    case XPathResultType.NodeSet:
        var nodes = (XPathNodeIterator)nav.Evaluate(expr);
        while (nodes != null && nodes.MoveNext())
        {
            if (nodes.Current == null)
                continue;
            if (nodes.Current.HasChildren)
            {
                var childIter = nodes.Current.SelectChildren(XPathNodeType.All);
                while (childIter.MoveNext())
                {
                    if (childIter.Current != null)
                        Console.WriteLine(childIter.Current.Value);
                }
            }
            else
            {
                Console.WriteLine(nodes.Current.Value);
            }
        }
        break;
}

对于这个示例,XML文件是简化的:

<?xml version="1.0" encoding="utf-8"?>
<Z>
  <X>
    <Code>ABC</Code>
  </X>
  <X>
    <Code>DEF</Code>
  </X>
</Z>

XPathExpression AddSort fails

AddSort方法接受一个XPath表达式,该表达式在上下文中绑定到已编译的XPathExpression。在您的示例中,XPathExpression是针对<Code>元素编译的。执行AddSort("Code")意味着您有以下XML:

<Code>
    <Code>
    </Code>
</Code>
相反,您可以将表达式编译为X:
const string query = "//Z/X";

或者你可以在当前节点(Code)上排序,.:

expr.AddSort(".", XmlSortOrder.Descending, XmlCaseOrder.None, "", XmlDataType.Text);

路径//Z/X/Code选择Code元素,那么Sort需要使用适当的相对表达式,在您的情况下

expr.AddSort(".",
             XmlSortOrder.Descending,
             XmlCaseOrder.None,
             "",
             XmlDataType.Text);

在AddSort()中使用"."代替"Code"从查询中删除"/Code",这取决于您是想选择x节点还是Code节点。目前,您正在查询Code-node,然后尝试通过将XPath"Code"应用于结果返回来对它们进行排序。但是相对于 Code-node,没有匹配"Code" 的内容。

使用Linq to Xml

using System.Xml.XPath;
var document = XDocument.Parse(@"<Z>
                                  <X>
                                    <Code>ABC</Code>
                                  </X>
                                  <X>
                                    <Code>DEF</Code>
                                  </X>
                                 </Z>");
var codeValues = document.XPathSelectElements("//Z/X/Code")
                          .Select(e => e.Value)
                          .OrderByDescending(e => e);

如果你愿意,你可以进一步简化它。不过你需要考虑性能。如果您的xml文件很大,我想这将不会执行得很好。如果您只有小文件,那么这样做的简单性胜过了小的性能损失。