#c# #xml #xpath
#c# #xml #xpath
Вопрос:
У меня есть этот XML:
<Meals>
<Meal>
<Food course="starter">Soup</Food>
<Food course="mains">Fish</Food>
<Food course="dessert">Ice cream</Food>
</Meal>
<Meal>
<Food course="starter">Soup</Food>
<Food course="mains">Chicken</Food>
<Food course="dessert">Cheese</Food>
</Meal>
<Meal>
<Food course="starter">Melon</Food>
<Food course="mains">lamb</Food>
<Food course="dessert">Ice cream</Food>
</Meal>
</Meals>
И это выражение XPath:
//Food[@course='dessert' and text() = 'Ice cream']
Это находит каждое десертное блюдо из мороженого. Я хочу добавить новый элемент после каждого соответствующего элемента следующим образом:
<Meals>
<Meal>
<Food course="starter">Soup</Food>
<Food course="mains">Fish</Food>
<Food course="dessert">Ice cream</Food>
<Review>enjoyed</Food>
</Meal>
<Meal>
<Food course="starter">Soup</Food>
<Food course="mains">Chicken</Food>
<Food course="dessert">Cheese</Food>
</Meal>
<Meal>
<Food course="starter">Melon</Food>
<Food course="mains">lamb</Food>
<Food course="dessert">Ice cream</Food>
<Review>enjoyed</Food>
</Meal>
</Meals>
Как я могу это сделать на C #, учитывая это выражение XPath? Выражение может измениться (например, вместо этого выбрать mains), и структура XML также может измениться. Независимо от этого, новый элемент должен быть вставлен после каждого соответствующего элемента.
Я знаю, что в XElement есть метод AddAfterSelf, но я не знаю, как использовать его в коллекции XElements, которую может возвращать выражение XPath.
Ответ №1:
LINQ для XML
var doc = XDocument.Parse("filepath");
var enjoyedMeals =
doc.Descendants("Meal")
.Where(meal => meal.Elements.Any(food => food.Attribute("course").Value == "desert"));
foreach (var meal in enjoyedMeals)
{
var review = new XElement("Review", "enjoyed");
meal.Elements.Add(review);
}
doc.ToString(); // contains <Review> elements
Комментарии:
1. Спасибо, это очень полезно. Однако мне приходится использовать выражение XPath, и структура XML может измениться, поэтому я не могу ссылаться на какие-либо свойства элемента в коде. Несмотря на это, это помогло мне найти решение, поэтому я очень ценю!
Ответ №2:
Это просто, но мне нужно было напоминание от @Fabio о том, что foreach — это то, что необходимо:
foreach (var element in foodXml.XPathSelectElements(xpathExpression))
{
element.AddAfterSelf(new XElement($"Review", "enjoyed"));
}
В foodXml теперь есть дополнительный элемент enjoyed после соответствующих элементов
Ответ №3:
И это выражение XPath:
//Food[@course='dessert' and text() = 'Ice cream']
Это находит каждое блюдо, в котором есть десертное блюдо из мороженого. Я хочу
чтобы добавить новый элемент после каждого соответствующего элемента, вот так:
Это выражение неверно. Вам нужно:
/Meals/Meal[Food[@course = 'dessert'] = 'Ice cream']
Комментарии:
1. Я отредактировал вопрос, чтобы было ясно, что XPath находит «каждое десертное блюдо из мороженого», а не «каждое блюдо, в котором есть десертное блюдо из мороженого». В вопросе указан правильный XPath. С этим проблем нет, мой вопрос заключался в том, как добавить элемент в C #. В любом случае спасибо