bmw318mt Ответов: 1

Удалить пространство имен из кода XML-C#


У меня есть XMLdoc , ниже приведен только фрагмент

& lt;АСУ ТП:ParameterList>
<АСУ ТП:ParameterGroup name= "группа">
<АСУ ТП:ParameterGroup name= "W1">
&ЛТ;АСУ ТП:параметр name="основание"и GT;1&ЛТ;/АСУ ТП:параметр&ГТ;
&ЛТ;АСУ ТП:параметр название="Петля"и GT;4&ЛТ;/АСУ ТП:параметр&ГТ;
&ЛТ;АСУ ТП:параметр название="провода"и GT;-1&ЛТ;/АСУ ТП:параметр&ГТ;
&ЛТ;АСУ ТП:параметр название="нити"и GT;-1&ЛТ;/АСУ ТП:параметр&ГТ;
< / АСУ ТП: ParameterGroup>
< / АСУ ТП: ParameterGroup>
< / АСУ ТП:ParameterList>

Мне нужно удалить пространство имен APCS и вернуть документ, как показано ниже

&ЛТ;Список_параметров&ГТ;
<ParameterGroup name= "группа">
<ParameterGroup name= "W1">
&ЛТ;параметр name="основание"и GT;1&ЛТ;/параметр&ГТ;
&ЛТ;имя параметра="петля"и GT;4&ЛТ;/параметр&ГТ;
< имя параметра= "провод"> -1< / параметр>
< имя параметра= "поток" > -1< / параметр>
< / ParameterGroup>
< / ParameterGroup>
< / ParameterList>

Что я уже пробовал:

У меня есть вспомогательные методы, которые могут удалить пространство имен, однако это также удаление числовых значений, т. е.
<Parameter name="BASE" />


Методы приведены ниже.

private static XmlElement changeNameSpaceRecursionHelper(XmlDocument doc, XmlElement fragment, string originalNamespace, string targetNamespace)
{
    string newElementNamespace = (fragment.NamespaceURI == originalNamespace ? targetNamespace : fragment.NamespaceURI);
    XmlElement newElement = doc.CreateElement(fragment.LocalName, newElementNamespace);

    foreach (XmlNode node in fragment.ChildNodes)
    {
        if (node is XmlElement)
        {
            newElement.AppendChild(changeNameSpaceRecursionHelper(doc, (XmlElement)node, originalNamespace, targetNamespace));
        }
    }

    foreach (XmlAttribute attr in fragment.Attributes)
    {
        string newAttributeNamespace = (attr.NamespaceURI == originalNamespace ? targetNamespace : attr.NamespaceURI);
        XmlAttribute newAttribute = doc.CreateAttribute(attr.LocalName, newAttributeNamespace);
        newAttribute.Value = attr.Value;
        newElement.Attributes.Append(newAttribute);
    }

    return newElement;
}

/// <summary>
/// Returns an Xml fragment with the namespace of all elements/attributes that belonged to originalNamespace changed to targetNamespace
/// <para>Note that any nodes other than Elements or their attributes will not be present in the returned fragment.</para>
/// </summary>
/// <param name="fragment">An XmlElement that is the root of the fragment to be processed</param>
/// <param name="originalNamespace">Namespace URI to be replaced.</param>
/// <param name="targetNamespace">Namespace URI to replace with.</param>
/// <returns>An Xml fragment with namespace replacement as required.</returns>
public static XmlElement ChangeNameSpace(XmlElement fragment, string originalNamespace, string targetNamespace)
{
    XmlDocument doc = new XmlDocument();
    return changeNameSpaceRecursionHelper(doc, fragment, originalNamespace, targetNamespace);
}

1 Ответов

Рейтинг:
2

Jon McKee

Поскольку вы заменяете его во всем XML документе я бы выбрал этот простой и читаемый подход:

using System.Xml;
using System.Text.RegularExpressions;

public static class XMLExtensions
{
    public static void RemoveNamespace(this XmlDocument document, string @namespace) =>
        document.InnerXml = Regex.Replace(
            document.InnerXml,
            $@"(?<=\</|\<){@namespace}:", 
            "");
}


EDIT: изменено регулярное выражение, чтобы перехватывать только пространства имен в тегах в случае, если некоторые данные называются АСУ ТП. Небольшое исправление в случае не жадной настройки по умолчанию.

EDIT2: пространство имен xmlns обычно включается только один раз, но если вам нужно программно удалить его, это сделает это:

using System.Xml;
using System.Text.RegularExpressions;

public static class XMLExtensions
{
    public static void RemoveNamespace(this XmlDocument document, string @namespace) =>
        document.InnerXml = Regex.Replace(
            document.InnerXml,
            $@"((?<=\</|\<){@namespace}:|xmlns:{@namespace}=""[^""]+"")", 
            "");
}


bmw318mt

Привет, спасибо за это решение, если я хочу удалить такой элемент и его закрывающий тег (у меня есть еще один элемент с именем ParameterList)
&ЛТ;Список_параметров префиксом xmlns:БТР="урна:ст-ком:СТ:fw2 по:АСУ ТП"и GT;

можно ли это сделать?

Jon McKee

Обновлено решение =)