#c# #xml #xpath
#c# #xml #xpath
Вопрос:
Я пытаюсь отсортировать результат запроса xpath, но это не удается.
Вывод вывода:
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 amp;amp; 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>
Ответ №1:
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);
Ответ №2:
Что ж, ваш путь //Z/X/Code
выбирает Code
элементы, затем сортировка должна использовать правильное относительное выражение, в вашем случае
expr.AddSort(".",
XmlSortOrder.Descending,
XmlCaseOrder.None,
"",
XmlDataType.Text);
Ответ №3:
Либо удалите «/ Code» из вашего запроса, мы используем «.» вместо «Code» в AddSort() — в зависимости от того, хотите ли вы выбрать X-узлы или Code-узлы. В настоящее время вы запрашиваете кодовые узлы, а затем пытаетесь отсортировать их по тому, что возвращает применение XPath «Code» к результату. Но нет ничего, что соответствовало бы «коду» относительно кодового узла.
Комментарии:
1. Что, если я хочу отсортировать содержимое и оставить там /Code ?
2. Извините, я не совсем уверен, чего вы хотите достичь. Как вы хотите, чтобы результат вашего запроса выглядел на первом уровне?
Ответ №4:
Некоторая альтернатива с использованием Linq для 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-файлы большие, я думаю, это не будет работать так же хорошо. Если у вас есть только небольшие файлы, простота этого перевешивает небольшое снижение производительности.
Комментарии:
1. Хотя технически это не неправильный ответ, он не связан с проблемой, с которой сталкивается OP. Это скорее альтернатива, чем решение.
2. Спасибо за голосование @DanAtkinson. В первом абзаце указано, что это альтернатива. Тем не менее, рабочая, более элегантная альтернатива.
3. Это был не я, кто проголосовал против вас ( i.imgur.com/o8Qgl9X.png ). Хотя я с радостью признаю, что я мог бы подделать это изображение. С какой целью, я не знаю.