Я ищу чистое, элегантное и умное решение для удаления пространств имен из всех элементов XML? Как бы это выглядело?
Определенный интерфейс:
public interface IXMLUtils
{
string RemoveAllNamespaces(string xmlDocument);
}
Пример XML для удаления NS:
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInserts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<insert>
<offer xmlns="http://schema.peters.com/doc_353/1/Types">0174587</offer>
<type2 xmlns="http://schema.peters.com/doc_353/1/Types">014717</type2>
<supplier xmlns="http://schema.peters.com/doc_353/1/Types">019172</supplier>
<id_frame xmlns="http://schema.peters.com/doc_353/1/Types" />
<type3 xmlns="http://schema.peters.com/doc_353/1/Types">
<type2 />
<main>false</main>
</type3>
<status xmlns="http://schema.peters.com/doc_353/1/Types">Some state</status>
</insert>
</ArrayOfInserts>
После вызова RemoveAllNamespaces (xmlWithLotOfNs) мы должны получить:
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfInserts>
<insert>
<offer >0174587</offer>
<type2 >014717</type2>
<supplier >019172</supplier>
<id_frame />
<type3 >
<type2 />
<main>false</main>
</type3>
<status >Some state</status>
</insert>
</ArrayOfInserts>
Предпочтительный язык решения - C # на .NET 3.5 SP1.
Ответы:
Ну вот и окончательный ответ. Я использовал отличную идею Джимми (которая, к сожалению, не является завершенной) и функцию полной рекурсии для правильной работы.
На основе интерфейса:
Я представляю здесь окончательное чистое и универсальное решение C # для удаления пространств имен XML:
Он работает на 100%, но я не очень много его тестировал, поэтому он может не покрывать некоторые особые случаи ... Но это хорошая основа для начала.
источник
Отмеченный наиболее полезный ответ имеет два недостатка:
Вот мой взгляд на это:
Пример кода здесь .
источник
xmlns
.(from a in e.Attributes().DistinctBy(x => x.Name.LocalName)
для делаlang=""ru-ru"" xml:lang=""ru-ru""
обязательный ответ с использованием LINQ:
источник
Это поможет :-)
источник
Поднимите его снова, в C # - добавлена строка для копирования атрибутов:
источник
Обязательный ответ с использованием XSLT:
источник
И это идеальное решение, которое также удалит элементы XSI. (Если вы удалите xmlns и не удалите XSI, .Net кричит на вас ...)
источник
Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Я знаю, что этот вопрос якобы решен, но я не был полностью доволен тем, как он был реализован. Я нашел еще один источник здесь, в блогах MSDN, у которого есть переопределенный
XmlTextWriter
класс, который удаляет пространства имен. Я немного подправил его, чтобы получить некоторые другие вещи, которые мне нужны, например красивое форматирование и сохранение корневого элемента. Вот что есть в моем проекте на данный момент.http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx
Класс
использование
источник
Это решение, основанное на принятом ответе Питера Стегнара.
Я использовал его, но (как отметили andygjp и Джон Сондерс) его код игнорирует атрибуты .
Мне тоже нужно было позаботиться об атрибутах, поэтому я адаптировал его код. Версия Энди была Visual Basic, это все еще C #.
Я знаю, что это было давно, но, возможно, однажды это кому-нибудь сэкономит время.
источник
Мне очень понравилось, куда идет Декстер, поэтому я перевел его на «беглый» метод расширения:
«Свободный» подход позволяет мне делать это:
источник
Вы можете сделать это с помощью Linq:
источник
Слегка измененный ответ Питера, это также отлично подойдет для атрибута, включая удаление пространства имен и префикса. Немного жаль, код выглядит немного некрасиво.
источник
Ответ Джимми и Питера очень помог, но они фактически удалили все атрибуты, поэтому я внес небольшие изменения:
источник
Немного поздно на вечеринку, но вот что я использовал недавно:
(взято из этой ветки MSDN )
Изменить Согласно комментарию ниже, похоже, что, хотя это удаляет префикс пространства имен из узлов, на самом деле он не удаляет атрибут xmlns. Для этого вам также необходимо сбросить имя каждого узла на его локальное имя (например, имя минус пространство имен)
источник
Чтобы атрибуты работали, цикл for для добавления атрибута должен идти после рекурсии, также необходимо проверить, если IsNamespaceDeclaration:
источник
Вот моя версия VB.NET Dexter Legaspi C # Version
источник
Другое решение, которое учитывает возможное чередование узлов TEXT и ELEMENT, например:
Код:
источник
Не прибегая к решению на основе XSLT, если вы хотите быть чистым, элегантным и умным, вам понадобится некоторая поддержка со стороны фреймворка, в частности, шаблон посетителя может сделать это проще простого. К сожалению, здесь его нет.
Я реализовал его, вдохновленный LINQ,
ExpressionVisitor
чтобы иметь аналогичную структуру. Таким образом, вы можете применить шаблон посетителя к объектам XML (LINQ-to-). (Я провел ограниченное тестирование, но, насколько я могу судить, он работает хорошо)ps, эта конкретная реализация использует некоторые функции .NET 4, чтобы сделать реализацию немного проще / чище (использование
dynamic
аргументов и аргументов по умолчанию). Сделать его совместимым с .NET 3.5, возможно, даже с .NET 2.0, не должно быть слишком сложно.Затем, чтобы реализовать посетителя, вот обобщенный вариант, который может изменять несколько пространств имен (и используемый префикс).
И небольшой вспомогательный метод, чтобы начать работу:
Затем, чтобы удалить пространство имен, вы можете назвать его так:
Используя этого посетителя, вы можете написать,
INamespaceMappingManager
чтобы удалить все пространства имен.источник
Простое решение, которое фактически переименовывает элементы на месте, а не создает копию, и довольно хорошо выполняет замену атрибутов.
Примечание: это не всегда сохраняет исходный порядок атрибутов, но я уверен, что вы можете легко изменить его, если это важно для вас.
Также обратите внимание, что это также может вызвать исключение, если у вас есть атрибуты XElement, которые уникальны только для пространства имен, например:
что действительно кажется внутренней проблемой. Но поскольку в вопросе указано, что выводится строка, а не XElement, в этом случае у вас может быть решение, которое выводит действительную строку, которая является недопустимым XElement.
Мне также понравился ответ jocull с использованием пользовательского XmlWriter, но когда я попробовал, у меня это не сработало. Хотя все выглядит правильно, я не мог сказать, имел ли класс XmlNoNamespaceWriter какой-либо эффект; это определенно не удаляло пространства имен, как я хотел.
источник
Добавление my, которое также очищает имена узлов, имеющих префиксы пространства имен:
источник
Я попробовал несколько первых решений, но у меня ничего не вышло. В основном проблема с удалением атрибутов, как уже упоминалось ранее. Я бы сказал, что мой подход очень похож на подход Джимми с использованием конструкторов XElement, которые принимают объект в качестве параметров.
источник
мой ответ, основанный на строковых манипуляциях,
самый легкий код,
источник
Вот Regex Replace one liner:
Вот образец: https://regex101.com/r/fopydN/6
Предупреждение: могут быть крайние случаи!
источник
user892217 ответ почти правильный. Он не будет компилироваться как есть, поэтому требует небольшого исправления рекурсивного вызова:
источник
Это сработало для меня.
источник
После долгих поисков решения именно этой проблемы эта конкретная страница, казалось, была наиболее жирной ... однако ничего не подходило точно, поэтому я выбрал старомодный способ и просто проанализировал то, что хотел. Надеюсь, это кому-то поможет. (Примечание: это также удаляет SOAP или аналогичный материал конверта.)
источник
Без воссоздания всей иерархии узлов:
источник
Я пробовал некоторые решения, но, как утверждают многие, есть некоторые крайние случаи.
Использовал некоторые из приведенных выше регулярных выражений, но пришел к выводу, что одношаговое регулярное выражение невозможно.
Итак, вот мое решение, двухэтапное регулярное выражение, найти теги, удалить теги, не изменять cdata:
Пока он у меня на 100% работает.
источник
Вот решение этой проблемы на основе регулярных выражений ...
источник
Я думаю, что это самый короткий ответ (но для таких конструкций, как у вас будет другое обсуждение, у меня также есть регулярное выражение для преобразования
"<bcm:info></bcm:info>"
в "<info></info>
", но оно не было оптимизировано, если кто-то спросит меня, я поделюсь им. Итак, мое решение:источник