Заменить текст в xml на заданный

149
24 ноября 2018, 19:20

Есть файл xml который имеет вид :

<?xml version="1.0" encoding="UTF-8"?>
<test title="This Xml will be updated">
    <line1>Xml has been renamed to New Xml</line1>
    <line1>Test has been renamed to Xml</line1>
    <line1>Xml has been renamed to Xml</line1>
    <line1>XmlXml has been renamed to New Xml</line1>
    <line1>Xml has been renamed to Xml</line1>
</test>

Нужно заменить добавить до всех слов Xml, слово New

Делаю так:

string prefix = "New";
string word = "Xml";
string regexPattern = $@"(?<!\b{prefix}\s+){word}\b";
string replacement = $"{prefix} $&";
XDocument xdoc = XDocument.Load(xmlFile.FullName);
foreach (var node in xdoc.Descendants())
{
    node.Value = Regex.Replace(node.Value, regexPattern, replacement);
    foreach (var attribute in node.Attributes())
    {
        attribute.Value = Regex.Replace(attribute.Value, regexPattern, replacement);
    }
}
return xdoc;

Замена происходит, но, почему то удаляются ноды <line1></line1> и xml становится в виде:

<?xml version="1.0" encoding="utf-8"?>
<test title="This New Xml will be updated">New Xml has been renamed to New XmlTest has been renamed to XmlNew Xml has been renamed to XmlXmlNew Xml has been renamed to New XmlNew Xml has been renamed to New Xml</test>

Что я делаю не так? В чем моя ошибка?

Answer 1

xdoc.Descendants() возвращает первым элементом корень всего документа, т.е. тег test со всем его содержимым.

Свойство XElement.Value:

Возвращает или задает сцепленное текстовое содержимое этого элемента.

Поэтому вы первой же итерацией просто уничтожаете все вложенные теги. Всё, дальше итераций не будет.

Починить можно так:

foreach (var node in xdoc.Root.Descendants())

или так:

foreach (var node in xdoc.Descendants("line1"))

Цикл по атрибутам надо будет вынести отдельно.

Еще один вариант (без правки заголовка цикла) — пропускать элементы, имеющие дочерние элементы:

if (!node.HasElements)
    node.Value = Regex.Replace(node.Value, regexPattern, replacement);

Тогда цикл по атрибутам можно оставить внутри.

(правильность самой регулярки не проверял)

READ ALSO
Странное исключение в модульных тестах Convert.ToBolean

Странное исключение в модульных тестах Convert.ToBolean

Использую фреймворк msunitПри обычном запуске программы Convert

161
C# Windows Form Показать данные в DataGrid

C# Windows Form Показать данные в DataGrid

Есть List обьектовКак показать их в DataGrid, изменить и вернуть обратно в List? (ItemsSource в MVVM WPF делает ето все)

171
Взять два цвета у объекта

Взять два цвета у объекта

Если у объекта есть два цвета (красный и синий), первым идет красный, к нему я получаю доступ PlayerCubeGetComponent()

146