вырезать вхождения тегов из XML - PullRequest
2 голосов
/ 03 ноября 2008

Я бы хотел исключить вхождения определенного тега, оставив внутренний XML-файл без изменений. Я хотел бы сделать это за один проход (вместо поиска, замены и повторного запуска с нуля). Например, из источника:

<element>
    <RemovalTarget Attribute="Something">
      Content Here
    </RemovalTarget>
</element>
<element>
  More Here
</element>

Я бы хотел, чтобы результат был:

<element>
  Content Here
</element>
<element>
  More Here
</element>

Я пробовал что-то вроде этого (прости меня, я новичок в Linq):

var elements = from element in doc.Descendants()
               where element.Name.LocalName == "RemovalTarget"
               select element;

foreach (var element in elements) {
    element.AddAfterSelf(element.Value);
    element.Remove();
}

но во второй раз в цикле я получаю нулевую ссылку, вероятно, потому что коллекция становится недействительной из-за ее изменения. Как эффективно удалить эти теги из потенциально большого документа?

Ответы [ 5 ]

3 голосов
/ 04 ноября 2008

Вам придется пропустить отложенное выполнение с помощью вызова ToList, что, вероятно, не повлияет на вашу производительность в больших документах, так как вы просто собираетесь выполнять итерации и замену с гораздо меньшим значением big-O, чем оригинал поиск. Как указал @jacob_c, я должен использовать element.Nodes () для его правильной замены, и, как указал @Panos, я должен перевернуть список, чтобы точно обрабатывать вложенные замены.

Кроме того, используйте XElement.ReplaceWith , намного быстрее, чем ваш текущий подход в больших документах:

var elements = doc.Descendants("RemovalTarget").ToList().Reverse();
/* reverse on the IList<T> may be faster than Reverse on the IEnumerable<T>,
 * needs benchmarking, but can't be any slower
 */

foreach (var element in elements) {
    element.ReplaceWith(element.Nodes());
}

И последнее замечание: при рассмотрении того, для чего МОЖЕТ быть использовано, я склонен согласиться с @Trull, что XSLT может быть тем, что вы на самом деле ищете, если, скажем, вы удаляете все теги скажем из документа , В противном случае, наслаждайтесь этой довольно приличной и довольно хорошо работающей реализацией LINQ to XML.

3 голосов
/ 03 ноября 2008

Рассматривали ли вы использование XSLT? Похоже, идеальный вариант, поскольку вы делаете именно то, для чего предназначен XSLT, превращая один XML-документ в другой. Система шаблонов без проблем погрузится во вложенную гадость для вас.

Здесь является базовым примером

0 голосов
/ 04 ноября 2008

В зависимости от того, как вы управляете своим XML, вы можете использовать регулярное выражение для удаления тегов.

Вот простое консольное приложение, которое демонстрирует использование регулярных выражений:

    static void Main(string[] args)
    {
        string content = File.ReadAllText(args[0]);

        Regex openTag = new Regex("<([/]?)RemovalTarget([^>]*)>", RegexOptions.Multiline);

        string cleanContent = openTag.Replace(content, string.Empty);
        File.WriteAllText(args[1], cleanContent);
    }

Это оставляет символы новой строки в файле, но не должно быть слишком сложно дополнить регулярное выражение.

0 голосов
/ 04 ноября 2008

Облегченным решением было бы использовать XmlReader для прохода через входной документ и XmlWriter для записи выходных данных.

Примечание: предложения XmlReader и XmlWriter являются абстрактными, используйте подходящие для вашей ситуации производные классы.

0 голосов
/ 03 ноября 2008

Я бы рекомендовал использовать XSLT, как рекомендовано Труллом, как лучшее решение.

Или вы можете использовать построитель строк и сопоставление регулярных выражений для удаления элементов.

Вы можете посмотреть, как пройтись по документу и работать с узлами и родительскими узлами, чтобы эффективно переместить код изнутри узла в родительский, но это было бы утомительно и совершенно не нужно для других потенциальных решений. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...