Comment supprimer tous les espaces de noms de XML avec C #?

104

Je recherche la solution propre, élégante et intelligente pour supprimer les espaces de noms de tous les éléments XML? Comment cela fonctionnerait-il?

Interface définie:

public interface IXMLUtils
{
        string RemoveAllNamespaces(string xmlDocument);
}

Exemple de XML pour supprimer 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>

Après avoir appelé RemoveAllNamespaces (xmlWithLotOfNs), nous devrions obtenir:

  <?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>

Le langage de solution préféré est C # sur .NET 3.5 SP1.

Peter Stegnar
la source
@JohnSaunders: Vous avez raison. Mais dans ce cas particulier, je dois faire une intégration système. Et c'était la seule option à l'époque.
Peter Stegnar
@PeterStegnar l'erreur est généralement le pirate qui a créé les formats hérités. Souvent, les développeurs abusent du XML de manière chronique. Les espaces de noms sont la première caractéristique folle à être écartée.
Gusdor

Réponses:

103

Eh bien, voici la réponse finale. J'ai utilisé une excellente idée de Jimmy (qui malheureusement n'est pas complète en soi) et une fonction de récursivité complète pour fonctionner correctement.

Basé sur l'interface:

string RemoveAllNamespaces(string xmlDocument);

Je représente ici la solution C # finale propre et universelle pour supprimer les espaces de noms XML:

//Implemented based on interface, not part of algorithm
public static string RemoveAllNamespaces(string xmlDocument)
{
    XElement xmlDocumentWithoutNs = RemoveAllNamespaces(XElement.Parse(xmlDocument));

    return xmlDocumentWithoutNs.ToString();
}

//Core recursion function
 private static XElement RemoveAllNamespaces(XElement xmlDocument)
    {
        if (!xmlDocument.HasElements)
        {
            XElement xElement = new XElement(xmlDocument.Name.LocalName);
            xElement.Value = xmlDocument.Value;

            foreach (XAttribute attribute in xmlDocument.Attributes())
                xElement.Add(attribute);

            return xElement;
        }
        return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));
    }

Ça marche à 100%, mais je ne l'ai pas beaucoup testé donc ça peut ne pas couvrir certains cas particuliers ... Mais c'est une bonne base pour commencer.

Peter Stegnar
la source
8
Dans quelle mesure cela fonctionne-t-il avec les attributs qui ont des espaces de noms? En fait, votre code ignore complètement les attributs.
John Saunders
6
Je réalise que les espaces de noms peuvent être utiles dans certaines applications, mais pas du tout dans les miennes; ils causaient un énorme désagrément. Cette solution a fonctionné pour moi.
JYelton
@John Saunders - Oui, j'ai utilisé cette solution et j'ai réalisé que vous aviez raison. Je poste une solution mise à jour en tant que réponse
Konrad Morawski
6
Cette solution n'a PAS fonctionné pour moi, car le code supprime tous les attributs ainsi que les espaces de noms. Bien sûr, quelques modifications peuvent fonctionner pour voir si l'attribut supprimé est un espace de noms ou un attribut
bigfoot
@KonradMorawski, malheureusement, je ne vois pas votre réponse ici. :(
Rami A.
63

La réponse la plus utile étiquetée présente deux défauts:

  • Il ignore les attributs
  • Cela ne fonctionne pas avec les éléments en "mode mixte"

Voici mon avis sur ceci:

 public static XElement RemoveAllNamespaces(XElement e)
 {
    return new XElement(e.Name.LocalName,
      (from n in e.Nodes()
        select ((n is XElement) ? RemoveAllNamespaces(n as XElement) : n)),
          (e.HasAttributes) ? 
            (from a in e.Attributes() 
               where (!a.IsNamespaceDeclaration)  
               select new XAttribute(a.Name.LocalName, a.Value)) : null);
  }          

Exemple de code ici .

Dexter Legaspi
la source
Malheureusement, cela n'a pas fonctionné pour moi, le même XML entré a été renvoyé. :(
Rami A.
@RamiA. pouvez-vous publier un extrait du code afin que nous puissions voir quel est le problème?
Dexter Legaspi le
Cela n'a pas fonctionné pour moi non plus. Je suppose que puisque vous copiez les attributs, vous copiez simplement xmlnsaussi.
MarioDS
1
Cela marche. Je l'ai utilisé ... mais j'ai réalisé que ce n'est pas un nettoyage en profondeur dans le sens où il ne supprime pas les attributs xmlns réels qui définissent l'espace de noms ... alors je l'ai mis à jour pour faire exactement cela ... et j'ai ajouté un exemple essentiel .
Dexter Legaspi
Besoin d'ajouter (from a in e.Attributes().DistinctBy(x => x.Name.LocalName)pour le caslang=""ru-ru"" xml:lang=""ru-ru""
smg
26

la réponse obligatoire via LINQ:

static XElement stripNS(XElement root) {
    return new XElement(
        root.Name.LocalName,
        root.HasElements ? 
            root.Elements().Select(el => stripNS(el)) :
            (object)root.Value
    );
}
static void Main() {
    var xml = XElement.Parse(@"<?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>");
    Console.WriteLine(stripNS(xml));
}
Jimmy
la source
3
Je suppose que vous pouvez montrer aux gens de VB que vous pouvez avoir un littéral XML en C # après tout.
Robert Harvey
1
@Robert, ce n'est pas un littéral XML. C'est une corde. Il y a une grande différence!
CoderDennis
Jimmy, tu es proche mais pas encore là. :) J'écris la solution finale basée sur votre idée. Je vais l'afficher là-bas.
Peter Stegnar
vous avez raison :) pendant que vous y êtes, je propose ma propre version du correctif.
Jimmy
3
Cela supprime tous les attributs, pas seulement les espaces de noms. Voir la réponse de Florian pour la solution.
Brian
25

Cela fera l'affaire :-)

foreach (XElement XE in Xml.DescendantsAndSelf())
{
    // Stripping the namespace by setting the name of the element to it's localname only
    XE.Name = XE.Name.LocalName;
    // replacing all attributes with attributes that are not namespaces and their names are set to only the localname
    XE.ReplaceAttributes((from xattrib in XE.Attributes().Where(xa => !xa.IsNamespaceDeclaration) select new XAttribute(xattrib.Name.LocalName, xattrib.Value)));
}
JSC
la source
Yo cela fonctionne très bien, non seulement cela fonctionne, mais cela n'affecte même pas le fichier, il écrit les données aussi Xelement en utilisant la méthode DescendantAndself. Merci mec!
shawn
travaille pour moi. Gère également CDATA que d'autres solutions perdent en cours de route.
paul
16

Reprenez-le à nouveau, en C # - ligne ajoutée pour copier les attributs:

    static XElement stripNS(XElement root)
    {
        XElement res = new XElement(
            root.Name.LocalName,
            root.HasElements ?
                root.Elements().Select(el => stripNS(el)) :
                (object)root.Value
        );

        res.ReplaceAttributes(
            root.Attributes().Where(attr => (!attr.IsNamespaceDeclaration)));

        return res;
    }
Florian Dürrbaum
la source
1
Fonctionne pour l'élément racine, mais pas pour les éléments imbriqués; les espaces de noms semblent simplement être renommés, peut-être automatiquement par XElement.ToString ().
Rami A.
Exactement ce dont j'avais besoin pour supprimer tous les espaces de noms, mais conserver les attributs.
Bassie
10

La réponse obligatoire avec XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no" encoding="UTF-8"/>

  <xsl:template match="/|comment()|processing-instruction()">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>
Annakata
la source
+1 pour le "obligatoire". :-) Je me demande toujours pourquoi la suppression des espaces de noms serait une décision judicieuse. Cela plante et brûle probablement sur <element ns: attr = "a" attr = "b" />.
Tomalak
Oh bien sûr, mais chaque technique d'élimination NS le fera dans une plus ou moins grande mesure. En tant que validité, je peux vous dire où j'en ai eu besoin: importer du XML tiers où ils ne peuvent pas trier un XSD valide mais insistent sur l'espacement des noms. La praticité règle finalement.
annakata
1
@annakata: La solution est plus simple que vous ne le pensez. Arrêtez d'activer. Refusez d'utiliser toute technique qui ne comprend pas XML. La seule raison pour laquelle nous sommes toujours obligés d'utiliser de telles ordures est que les gens continuent de dire «oui», alors qu'ils ont besoin de dire «non» un peu plus souvent. Les normes ont plus de 10 ans! Sinon, pourquoi avons-nous encore des logiciels qui ne comprennent pas les espaces de noms XML, sauf que nous continuons à leur permettre d'exister?
John Saunders
3
@John - ha, il y a ces choses qui devraient être faites, et il y a celles qui, selon la direction, seront faites. Tout est pour le mieux dans le meilleur de tous les mondes possibles.
annakata
1
@Tomalak, un cas d'utilisation pourrait être si vous devez convertir en JSON et que les déclarations d'espace de noms interfèrent avec ce processus.
devlord
10

Et c'est la solution parfaite qui supprimera également les éléments XSI. (Si vous supprimez les xmlns et ne supprimez pas XSI, .Net vous crie dessus ...)

string xml = node.OuterXml;
//Regex below finds strings that start with xmlns, may or may not have :and some text, then continue with =
//and ", have a streach of text that does not contain quotes and end with ". similar, will happen to an attribute
// that starts with xsi.
string strXMLPattern = @"xmlns(:\w+)?=""([^""]+)""|xsi(:\w+)?=""([^""]+)""";
xml = Regex.Replace(xml, strXMLPattern, "");
David
la source
1
Je devrais lire ceci il y a 2 heures. A fait presque la même expression régulière, la seule chose qui fonctionnait, en XML complexe, avec de nombreux espaces de noms, attributs, etc.
TPAKTOPA
Gardez à l'esprit que vous devrez peut-être nettoyer des éléments comme par exemple <xxx: tagname>. J'ai utilisé le code suivant (avertissement, fonctionne sur ma machine): Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Edwin
9

Je sais que cette question est censée être résolue, mais je n'étais pas totalement satisfaite de la façon dont elle a été mise en œuvre. J'ai trouvé une autre source ici sur les blogs MSDN qui a une XmlTextWriterclasse remplacée qui supprime les espaces de noms. Je l'ai un peu modifié pour obtenir d'autres éléments que je souhaitais, tels que le joli formatage et la préservation de l'élément racine. Voici ce que j'ai dans mon projet en ce moment.

http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx

Classe

/// <summary>
/// Modified XML writer that writes (almost) no namespaces out with pretty formatting
/// </summary>
/// <seealso cref="http://blogs.msdn.com/b/kaevans/archive/2004/08/02/206432.aspx"/>
public class XmlNoNamespaceWriter : XmlTextWriter
{
    private bool _SkipAttribute = false;
    private int _EncounteredNamespaceCount = 0;

    public XmlNoNamespaceWriter(TextWriter writer)
        : base(writer)
    {
        this.Formatting = System.Xml.Formatting.Indented;
    }

    public override void WriteStartElement(string prefix, string localName, string ns)
    {
        base.WriteStartElement(null, localName, null);
    }

    public override void WriteStartAttribute(string prefix, string localName, string ns)
    {
        //If the prefix or localname are "xmlns", don't write it.
        //HOWEVER... if the 1st element (root?) has a namespace we will write it.
        if ((prefix.CompareTo("xmlns") == 0
                || localName.CompareTo("xmlns") == 0)
            && _EncounteredNamespaceCount++ > 0)
        {
            _SkipAttribute = true;
        }
        else
        {
            base.WriteStartAttribute(null, localName, null);
        }
    }

    public override void WriteString(string text)
    {
        //If we are writing an attribute, the text for the xmlns
        //or xmlns:prefix declaration would occur here.  Skip
        //it if this is the case.
        if (!_SkipAttribute)
        {
            base.WriteString(text);
        }
    }

    public override void WriteEndAttribute()
    {
        //If we skipped the WriteStartAttribute call, we have to
        //skip the WriteEndAttribute call as well or else the XmlWriter
        //will have an invalid state.
        if (!_SkipAttribute)
        {
            base.WriteEndAttribute();
        }
        //reset the boolean for the next attribute.
        _SkipAttribute = false;
    }

    public override void WriteQualifiedName(string localName, string ns)
    {
        //Always write the qualified name using only the
        //localname.
        base.WriteQualifiedName(localName, null);
    }
}

Usage

//Save the updated document using our modified (almost) no-namespace XML writer
using(StreamWriter sw = new StreamWriter(this.XmlDocumentPath))
using(XmlNoNamespaceWriter xw = new XmlNoNamespaceWriter(sw))
{
    //This variable is of type `XmlDocument`
    this.XmlDocumentRoot.Save(xw);
}
plaisanter
la source
1
Votre réponse est la seule qui ne ressemble pas à un hack, cependant, l'exemple d'origine dans le billet de blog référencé est plus correct car si vous ne supprimez pas l'espace de noms dans le nœud racine, tous les nœuds enfants et attributs sans namespace héritera de l'espace de noms racine.
ténor
8

C'est une solution basée sur la réponse acceptée de Peter Stegnar.

Je l'ai utilisé, mais (comme andygjp et John Saunders l'ont fait remarquer) son code ignore les attributs .

J'avais aussi besoin de m'occuper des attributs, j'ai donc adapté son code. La version d'Andy était Visual Basic, c'est toujours c #.

Je sais que ça fait un moment, mais peut-être que ça fera gagner du temps à quelqu'un un jour.

    private static XElement RemoveAllNamespaces(XElement xmlDocument)
    {
        XElement xmlDocumentWithoutNs = removeAllNamespaces(xmlDocument);
        return xmlDocumentWithoutNs;
    }

    private static XElement removeAllNamespaces(XElement xmlDocument)
    {
        var stripped = new XElement(xmlDocument.Name.LocalName);            
        foreach (var attribute in
                xmlDocument.Attributes().Where(
                attribute =>
                    !attribute.IsNamespaceDeclaration &&
                    String.IsNullOrEmpty(attribute.Name.NamespaceName)))
        {
            stripped.Add(new XAttribute(attribute.Name.LocalName, attribute.Value));
        }
        if (!xmlDocument.HasElements)
        {
            stripped.Value = xmlDocument.Value;
            return stripped;
        }
        stripped.Add(xmlDocument.Elements().Select(
            el =>
                RemoveAllNamespaces(el)));            
        return stripped;
    }
Konrad Morawski
la source
6

J'ai vraiment aimé où Dexter va là-haut, alors je l'ai traduit en une méthode d'extension «fluide»:

/// <summary>
/// Returns the specified <see cref="XElement"/>
/// without namespace qualifiers on elements and attributes.
/// </summary>
/// <param name="element">The element</param>
public static XElement WithoutNamespaces(this XElement element)
{
    if (element == null) return null;

    #region delegates:

        Func<XNode, XNode> getChildNode = e => (e.NodeType == XmlNodeType.Element) ? (e as XElement).WithoutNamespaces() : e;

        Func<XElement, IEnumerable<XAttribute>> getAttributes = e => (e.HasAttributes) ?
            e.Attributes()
                .Where(a => !a.IsNamespaceDeclaration)
                .Select(a => new XAttribute(a.Name.LocalName, a.Value))
            :
            Enumerable.Empty<XAttribute>();

        #endregion

    return new XElement(element.Name.LocalName,
        element.Nodes().Select(getChildNode),
        getAttributes(element));
}

L'approche «fluide» me permet de faire ceci:

var xml = File.ReadAllText(presentationFile);
var xDoc = XDocument.Parse(xml);
var xRoot = xDoc.Root.WithoutNamespaces();
rasx
la source
1
Merci pour cette solution! Fonctionne très bien pour mon problème.
AngieM
1
C'était donc idéal parce que cela fonctionnait sur les attributs. A pu l'utiliser sans problème. Merci
julian guppy
4

Vous pouvez le faire en utilisant Linq:

public static string RemoveAllNamespaces(string xmlDocument)
{
    var xml = XElement.Parse(xmlDocument);
    xml.Descendants().Select(o => o.Name = o.Name.LocalName).ToArray();
    return xml.ToString();
}
Philip Atz
la source
3

Légèrement modifié la réponse de Peter, cela fonctionnerait bien pour l'attribut également, y compris la suppression de l'espace de noms et du préfixe. Un peu désolé pour le code semble un peu moche.

 private static XElement RemoveAllNamespaces(XElement xmlDocument)
        {
            if (!xmlDocument.HasElements)
            {
                XElement xElement = new XElement(xmlDocument.Name.LocalName);
                xElement.Value = xmlDocument.Value;

                foreach (XAttribute attribute in xmlDocument.Attributes())
                {
                    xElement.Add(new XAttribute(attribute.Name.LocalName, attribute.Value));
                }

                return xElement;
            }

            else
            {
                XElement xElement = new XElement(xmlDocument.Name.LocalName,  xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));

                foreach (XAttribute attribute in xmlDocument.Attributes())
                {
                    xElement.Add(new XAttribute(attribute.Name.LocalName, attribute.Value));
                }

                return xElement;
            }

    }
JackG
la source
+1 Cela a fonctionné pour moi. Cependant, il laisse les attributs qui faisaient partie de la définition de l'espace de noms (seul le préfixe xmlns a été supprimé) mais ils n'affectent pas actuellement la sérialisation.
Rami A.
2

La réponse de Jimmy et Peter a été d'une grande aide, mais ils ont en fait supprimé tous les attributs, j'ai donc fait une légère modification:

Imports System.Runtime.CompilerServices

Friend Module XElementExtensions

    <Extension()> _
    Public Function RemoveAllNamespaces(ByVal element As XElement) As XElement
        If element.HasElements Then
            Dim cleanElement = RemoveAllNamespaces(New XElement(element.Name.LocalName, element.Attributes))
            cleanElement.Add(element.Elements.Select(Function(el) RemoveAllNamespaces(el)))
            Return cleanElement
        Else
            Dim allAttributesExceptNamespaces = element.Attributes.Where(Function(attr) Not attr.IsNamespaceDeclaration)
            element.ReplaceAttributes(allAttributesExceptNamespaces)
            Return element
        End If

    End Function

End Module
andygjp
la source
2

Un peu tard à la fête sur celui-ci mais voici ce que j'ai utilisé récemment:

var doc = XDocument.Parse(xmlString);
doc.Root.DescendantNodesAndSelf().OfType<XElement>().Attributes().Where(att => att.IsNamespaceDeclaration).Remove();

(extrait de ce fil MSDN )

Modifier Selon le commentaire ci-dessous, il semble que bien que cela supprime le préfixe d'espace de noms des nœuds, il ne supprime pas réellement l'attribut xmlns. Pour ce faire, vous devez également réinitialiser le nom de chaque nœud à son nom local (par exemple, nom moins espace de noms)

foreach (var node in doc.Root.DescendantNodesAndSelf().OfType<XElement>())
{
    node.Name = node.Name.LocalName;
}
MarcE
la source
Cela ne semble pas fonctionner? Il trouve toutes les déclarations d'espace de noms, mais appeler Remove () sur cette collection ne fait rien. J'ai essayé result.ToString (), et la chaîne résultante a toujours l'attribut xmlns. Est-ce que je fais quelque chose de mal?
Jimmy
Cela a fonctionné pour ce dont j'avais besoin à l'époque, mais maintenant je regarde en arrière, ce n'est pas à 100%. Il supprime les préfixes d'espace de noms des nœuds (ce dont j'avais besoin) mais vous avez raison de laisser l'attribut xmlns derrière. Bizarrement, cet attribut n'est reconnu par aucune des méthodes XDocument non plus!
MarcE
1

Pour que les attributs fonctionnent, la boucle for pour l'ajout d'attribut doit aller après la récursivité, vous devez également vérifier si IsNamespaceDeclaration:

private static XElement RemoveAllNamespaces(XElement xmlDocument)
{
    XElement xElement;

    if (!xmlDocument.HasElements)
    {
        xElement = new XElement(xmlDocument.Name.LocalName) { Value = xmlDocument.Value };
    }
    else
    {
        xElement = new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(RemoveAllNamespaces));
    }

    foreach (var attribute in xmlDocument.Attributes())
    {
        if (!attribute.IsNamespaceDeclaration)
        {
            xElement.Add(attribute);
        }
    }

    return xElement;
}
user892217
la source
1

Voici ma version VB.NET de la version C # de Dexter Legaspi

Shared Function RemoveAllNamespaces(ByVal e As XElement) As XElement
        Return New XElement(e.Name.LocalName, New Object() {(From n In e.Nodes Select If(TypeOf n Is XElement, RemoveAllNamespaces(TryCast(n, XElement)), n)), If(e.HasAttributes, (From a In e.Attributes Select a), Nothing)})
End Function
user2740574
la source
1

Une autre solution qui prend en compte les nœuds TEXT et ELEMENT éventuellement entrelacés, par exemple:

<parent>
    text1
    <child1/>
    text2
    <child2/>
</parent>

Code:

using System.Linq;

namespace System.Xml.Linq
{
    public static class XElementTransformExtensions
    {
        public static XElement WithoutNamespaces(this XElement source)
        {
            return new XElement(source.Name.LocalName,
                source.Attributes().Select(WithoutNamespaces),
                source.Nodes().Select(WithoutNamespaces)
            );
        }

        public static XAttribute WithoutNamespaces(this XAttribute source)
        {
            return !source.IsNamespaceDeclaration
                ? new XAttribute(source.Name.LocalName, source.Value)
                : default(XAttribute);
        }

        public static XNode WithoutNamespaces(this XNode source)
        {
            return
                source is XElement
                    ? WithoutNamespaces((XElement)source)
                    : source;
        }
    }
}
estime
la source
1

Sans recourir à une solution basée sur XSLT, si vous voulez être propre, élégant et intelligent, vous auriez besoin du support du framework, en particulier, le modèle de visiteur pourrait en faire un jeu d'enfant. Malheureusement, il n'est pas disponible ici.

Je l'ai implémenté inspiré par LINQ ExpressionVisitorpour avoir une structure similaire. Avec cela, vous pouvez appliquer le modèle de visiteur aux objets XML (LINQ-to-). (J'ai fait des tests limités à ce sujet mais cela fonctionne bien pour autant que je sache)

public abstract class XObjectVisitor
{
    public virtual XObject Visit(XObject node)
    {
        if (node != null)
            return node.Accept(this);
        return node;
    }

    public ReadOnlyCollection<XObject> Visit(IEnumerable<XObject> nodes)
    {
        return nodes.Select(node => Visit(node))
            .Where(node => node != null)
            .ToList()
            .AsReadOnly();
    }

    public T VisitAndConvert<T>(T node) where T : XObject
    {
        if (node != null)
            return Visit(node) as T;
        return node;
    }

    public ReadOnlyCollection<T> VisitAndConvert<T>(IEnumerable<T> nodes) where T : XObject
    {
        return nodes.Select(node => VisitAndConvert(node))
            .Where(node => node != null)
            .ToList()
            .AsReadOnly();
    }

    protected virtual XObject VisitAttribute(XAttribute node)
    {
        return node.Update(node.Name, node.Value);
    }

    protected virtual XObject VisitComment(XComment node)
    {
        return node.Update(node.Value);
    }

    protected virtual XObject VisitDocument(XDocument node)
    {
        return node.Update(
            node.Declaration,
            VisitAndConvert(node.Nodes())
        );
    }

    protected virtual XObject VisitElement(XElement node)
    {
        return node.Update(
            node.Name,
            VisitAndConvert(node.Attributes()),
            VisitAndConvert(node.Nodes())
        );
    }

    protected virtual XObject VisitDocumentType(XDocumentType node)
    {
        return node.Update(
            node.Name,
            node.PublicId,
            node.SystemId,
            node.InternalSubset
        );
    }

    protected virtual XObject VisitProcessingInstruction(XProcessingInstruction node)
    {
        return node.Update(
            node.Target,
            node.Data
        );
    }

    protected virtual XObject VisitText(XText node)
    {
        return node.Update(node.Value);
    }

    protected virtual XObject VisitCData(XCData node)
    {
        return node.Update(node.Value);
    }

    #region Implementation details
    internal InternalAccessor Accessor
    {
        get { return new InternalAccessor(this); }
    }

    internal class InternalAccessor
    {
        private XObjectVisitor visitor;
        internal InternalAccessor(XObjectVisitor visitor) { this.visitor = visitor; }

        internal XObject VisitAttribute(XAttribute node) { return visitor.VisitAttribute(node); }
        internal XObject VisitComment(XComment node) { return visitor.VisitComment(node); }
        internal XObject VisitDocument(XDocument node) { return visitor.VisitDocument(node); }
        internal XObject VisitElement(XElement node) { return visitor.VisitElement(node); }
        internal XObject VisitDocumentType(XDocumentType node) { return visitor.VisitDocumentType(node); }
        internal XObject VisitProcessingInstruction(XProcessingInstruction node) { return visitor.VisitProcessingInstruction(node); }
        internal XObject VisitText(XText node) { return visitor.VisitText(node); }
        internal XObject VisitCData(XCData node) { return visitor.VisitCData(node); }
    }
    #endregion
}

public static class XObjectVisitorExtensions
{
    #region XObject.Accept "instance" method
    public static XObject Accept(this XObject node, XObjectVisitor visitor)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(visitor, "visitor");

        // yay, easy dynamic dispatch
        Acceptor acceptor = new Acceptor(node as dynamic);
        return acceptor.Accept(visitor);
    }
    private class Acceptor
    {
        public Acceptor(XAttribute node) : this(v => v.Accessor.VisitAttribute(node)) { }
        public Acceptor(XComment node) : this(v => v.Accessor.VisitComment(node)) { }
        public Acceptor(XDocument node) : this(v => v.Accessor.VisitDocument(node)) { }
        public Acceptor(XElement node) : this(v => v.Accessor.VisitElement(node)) { }
        public Acceptor(XDocumentType node) : this(v => v.Accessor.VisitDocumentType(node)) { }
        public Acceptor(XProcessingInstruction node) : this(v => v.Accessor.VisitProcessingInstruction(node)) { }
        public Acceptor(XText node) : this(v => v.Accessor.VisitText(node)) { }
        public Acceptor(XCData node) : this(v => v.Accessor.VisitCData(node)) { }

        private Func<XObjectVisitor, XObject> accept;
        private Acceptor(Func<XObjectVisitor, XObject> accept) { this.accept = accept; }

        public XObject Accept(XObjectVisitor visitor) { return accept(visitor); }
    }
    #endregion

    #region XObject.Update "instance" method
    public static XObject Update(this XAttribute node, XName name, string value)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");
        Validation.CheckArgumentNull(value, "value");

        return new XAttribute(name, value);
    }
    public static XObject Update(this XComment node, string value = null)
    {
        Validation.CheckNullReference(node);

        return new XComment(value);
    }
    public static XObject Update(this XDocument node, XDeclaration declaration = null, params object[] content)
    {
        Validation.CheckNullReference(node);

        return new XDocument(declaration, content);
    }
    public static XObject Update(this XElement node, XName name, params object[] content)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");

        return new XElement(name, content);
    }
    public static XObject Update(this XDocumentType node, string name, string publicId = null, string systemId = null, string internalSubset = null)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(name, "name");

        return new XDocumentType(name, publicId, systemId, internalSubset);
    }
    public static XObject Update(this XProcessingInstruction node, string target, string data)
    {
        Validation.CheckNullReference(node);
        Validation.CheckArgumentNull(target, "target");
        Validation.CheckArgumentNull(data, "data");

        return new XProcessingInstruction(target, data);
    }
    public static XObject Update(this XText node, string value = null)
    {
        Validation.CheckNullReference(node);

        return new XText(value);
    }
    public static XObject Update(this XCData node, string value = null)
    {
        Validation.CheckNullReference(node);

        return new XCData(value);
    }
    #endregion
}

public static class Validation
{
    public static void CheckNullReference<T>(T obj) where T : class
    {
        if (obj == null)
            throw new NullReferenceException();
    }

    public static void CheckArgumentNull<T>(T obj, string paramName) where T : class
    {
        if (obj == null)
            throw new ArgumentNullException(paramName);
    }
}

ps, cette implémentation particulière utilise certaines fonctionnalités de .NET 4 pour rendre l'implémentation un peu plus facile / plus propre (utilisation des dynamicarguments par défaut). Il ne devrait pas être trop difficile de le rendre compatible .NET 3.5, peut-être même compatible .NET 2.0.

Ensuite, pour implémenter le visiteur, en voici un généralisé qui peut changer plusieurs espaces de noms (et le préfixe utilisé).

public class ChangeNamespaceVisitor : XObjectVisitor
{
    private INamespaceMappingManager manager;
    public ChangeNamespaceVisitor(INamespaceMappingManager manager)
    {
        Validation.CheckArgumentNull(manager, "manager");

        this.manager = manager;
    }

    protected INamespaceMappingManager Manager { get { return manager; } }

    private XName ChangeNamespace(XName name)
    {
        var mapping = Manager.GetMapping(name.Namespace);
        return mapping.ChangeNamespace(name);
    }

    private XObject ChangeNamespaceDeclaration(XAttribute node)
    {
        var mapping = Manager.GetMapping(node.Value);
        return mapping.ChangeNamespaceDeclaration(node);
    }

    protected override XObject VisitAttribute(XAttribute node)
    {
        if (node.IsNamespaceDeclaration)
            return ChangeNamespaceDeclaration(node);
        return node.Update(ChangeNamespace(node.Name), node.Value);
    }

    protected override XObject VisitElement(XElement node)
    {
        return node.Update(
            ChangeNamespace(node.Name),
            VisitAndConvert(node.Attributes()),
            VisitAndConvert(node.Nodes())
        );
    }
}

// and all the gory implementation details
public class NamespaceMappingManager : INamespaceMappingManager
{
    private Dictionary<XNamespace, INamespaceMapping> namespaces = new Dictionary<XNamespace, INamespaceMapping>();

    public NamespaceMappingManager Add(XNamespace fromNs, XNamespace toNs, string toPrefix = null)
    {
        var item = new NamespaceMapping(fromNs, toNs, toPrefix);
        namespaces.Add(item.FromNs, item);
        return this;
    }

    public INamespaceMapping GetMapping(XNamespace fromNs)
    {
        INamespaceMapping mapping;
        if (!namespaces.TryGetValue(fromNs, out mapping))
            mapping = new NullMapping();
        return mapping;
    }

    private class NullMapping : INamespaceMapping
    {
        public XName ChangeNamespace(XName name)
        {
            return name;
        }

        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            return node.Update(node.Name, node.Value);
        }
    }

    private class NamespaceMapping : INamespaceMapping
    {
        private XNamespace fromNs;
        private XNamespace toNs;
        private string toPrefix;
        public NamespaceMapping(XNamespace fromNs, XNamespace toNs, string toPrefix = null)
        {
            this.fromNs = fromNs ?? "";
            this.toNs = toNs ?? "";
            this.toPrefix = toPrefix;
        }

        public XNamespace FromNs { get { return fromNs; } }
        public XNamespace ToNs { get { return toNs; } }
        public string ToPrefix { get { return toPrefix; } }

        public XName ChangeNamespace(XName name)
        {
            return name.Namespace == fromNs
                ? toNs + name.LocalName
                : name;
        }

        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            if (node.Value == fromNs.NamespaceName)
            {
                if (toNs == XNamespace.None)
                    return null;
                var xmlns = !String.IsNullOrWhiteSpace(toPrefix)
                    ? (XNamespace.Xmlns + toPrefix)
                    : node.Name;
                return node.Update(xmlns, toNs.NamespaceName);
            }
            return node.Update(node.Name, node.Value);
        }
    }
}

public interface INamespaceMappingManager
{
    INamespaceMapping GetMapping(XNamespace fromNs);
}

public interface INamespaceMapping
{
    XName ChangeNamespace(XName name);
    XObject ChangeNamespaceDeclaration(XAttribute node);
}

Et une petite méthode d'aide pour lancer le bal:

T ChangeNamespace<T>(T node, XNamespace fromNs, XNamespace toNs, string toPrefix = null) where T : XObject
{
    return node.Accept(
        new ChangeNamespaceVisitor(
            new NamespaceMappingManager()
                .Add(fromNs, toNs, toPrefix)
        )
    ) as T;
}

Ensuite, pour supprimer un espace de noms, vous pouvez l'appeler comme ceci:

var doc = ChangeNamespace(XDocument.Load(pathToXml),
    fromNs: "http://schema.peters.com/doc_353/1/Types",
    toNs: null);

En utilisant ce visiteur, vous pouvez écrire un INamespaceMappingManagerpour supprimer tous les espaces de noms.

T RemoveAllNamespaces<T>(T node) where T : XObject
{
    return node.Accept(
        new ChangeNamespaceVisitor(new RemoveNamespaceMappingManager())
    ) as T;
}

public class RemoveNamespaceMappingManager : INamespaceMappingManager
{
    public INamespaceMapping GetMapping(XNamespace fromNs)
    {
        return new RemoveNamespaceMapping();
    }

    private class RemoveNamespaceMapping : INamespaceMapping
    {
        public XName ChangeNamespace(XName name)
        {
            return name.LocalName;
        }

        public XObject ChangeNamespaceDeclaration(XAttribute node)
        {
            return null;
        }
    }
}
Jeff Mercado
la source
1

Solution simple qui renomme réellement les éléments sur place, ne crée pas de copie, et fait un très bon travail de remplacement des attributs.

public void RemoveAllNamespaces(ref XElement value)
{
  List<XAttribute> attributesToRemove = new List<XAttribute>();
  foreach (void e_loopVariable in value.DescendantsAndSelf) {
    e = e_loopVariable;
    if (e.Name.Namespace != XNamespace.None) {
      e.Name = e.Name.LocalName;
    }
    foreach (void a_loopVariable in e.Attributes) {
      a = a_loopVariable;
      if (a.IsNamespaceDeclaration) {
        //do not keep it at all
        attributesToRemove.Add(a);
      } else if (a.Name.Namespace != XNamespace.None) {
        e.SetAttributeValue(a.Name.LocalName, a.Value);
        attributesToRemove.Add(a);
      }
    }
  }
  foreach (void a_loopVariable in attributesToRemove) {
    a = a_loopVariable;
    a.Remove();
  }
}

Remarque: cela ne préserve pas toujours l'ordre des attributs d'origine, mais je suis sûr que vous pouvez le modifier pour le faire assez facilement si cela est important pour vous.

Notez également que cela pourrait également lever une exception, si vous aviez des attributs XElement qui ne sont uniques qu'avec l'espace de noms, comme:

<root xmlns:ns1="a" xmlns:ns2="b">
    <elem ns1:dupAttrib="" ns2:dupAttrib="" />
</root>

ce qui semble vraiment être un problème inhérent. Mais comme la question indiquait la sortie d'une chaîne, pas d'un XElement, dans ce cas, vous pourriez avoir une solution qui afficherait une chaîne valide qui était un XElement non valide.

J'ai aussi aimé la réponse de jocull en utilisant un XmlWriter personnalisé, mais quand je l'ai essayé, cela n'a pas fonctionné pour moi. Bien que tout semble correct, je ne pouvais pas dire si la classe XmlNoNamespaceWriter avait un effet quelconque; il ne supprimait certainement pas les espaces de noms comme je le voulais.

Abaque
la source
1

L'ajout de my qui nettoie également le nom des nœuds qui ont des préfixes d'espace de noms:

    public static string RemoveAllNamespaces(XElement element)
    {
        string tex = element.ToString();
        var nsitems = element.DescendantsAndSelf().Select(n => n.ToString().Split(' ', '>')[0].Split('<')[1]).Where(n => n.Contains(":")).DistinctBy(n => n).ToArray();

        //Namespace prefix on nodes: <a:nodename/>
        tex = nsitems.Aggregate(tex, (current, nsnode) => current.Replace("<"+nsnode + "", "<" + nsnode.Split(':')[1] + ""));
        tex = nsitems.Aggregate(tex, (current, nsnode) => current.Replace("</" + nsnode + "", "</" + nsnode.Split(':')[1] + ""));

        //Namespace attribs
        var items = element.DescendantsAndSelf().SelectMany(d => d.Attributes().Where(a => a.IsNamespaceDeclaration || a.ToString().Contains(":"))).DistinctBy(o => o.Value);
        tex = items.Aggregate(tex, (current, xAttribute) => current.Replace(xAttribute.ToString(), ""));

        return tex;
    }
Loup5
la source
1

J'ai essayé les premières solutions et je n'ai pas fonctionné pour moi. Principalement le problème avec les attributs supprimés comme les autres l'ont déjà mentionné. Je dirais que mon approche est très similaire à celle de Jimmy en utilisant les constructeurs XElement qui prennent l'objet comme paramètres.

public static XElement RemoveAllNamespaces(this XElement element)
{
    return new XElement(element.Name.LocalName,
                        element.HasAttributes ? element.Attributes().Select(a => new XAttribute(a.Name.LocalName, a.Value)) : null,
                        element.HasElements ? element.Elements().Select(e => RemoveAllNamespaces(e)) : null,
                        element.Value);
}
sww
la source
1

ma réponse,
code basé sur la manipulation de chaînes, le plus léger,

public static string hilangkanNamespace(string instrXML)
    {
        char chrOpeningTag = '<';
        char chrClosingTag = '>';
        char chrSpasi = ' ';
        int intStartIndex = 0;
        do
        {
            int intIndexKu = instrXML.IndexOf(chrOpeningTag, intStartIndex);
            if (intIndexKu < 0)
                break; //kalau dah ga ketemu keluar
            int intStart = instrXML.IndexOfAny(new char[] { chrSpasi, chrClosingTag }, intIndexKu + 1); //mana yang ketemu duluan
            if (intStart < 0)
                break; //kalau dah ga ketemu keluar
            int intStop = instrXML.IndexOf(chrClosingTag, intStart);
            if (intStop < 0)
                break; //kalau dah ga ketemu keluar
            else
                intStop--; //exclude si closingTag
            int intLengthToStrip = intStop - intStart + 1;
            instrXML = instrXML.Remove(intStart, intLengthToStrip);
            intStartIndex = intStart;
        } while (true);

        return instrXML;
    }
Si Livan
la source
1

Voici Regex Replace one liner:

public static string RemoveNamespaces(this string xml)
{
    return Regex.Replace(xml, "((?<=<|<\\/)|(?<= ))[A-Za-z0-9]+:| xmlns(:[A-Za-z0-9]+)?=\".*?\"", "");
}

Voici un exemple: https://regex101.com/r/fopydN/6

Attention: il peut y avoir des cas extrêmes!

Visar
la source
0

La réponse de user892217 est presque correcte. Il ne se compilera pas tel quel, il nécessite donc une légère correction de l'appel récursif:

private static XElement RemoveAllNamespaces(XElement xmlDocument)
{
    XElement xElement;

    if (!xmlDocument.HasElements)
    {
        xElement = new XElement(xmlDocument.Name.LocalName) { Value = xmlDocument.Value };
    }
    else
    {
        xElement = new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(x => RemoveAllNamespaces(x)));
    }

    foreach (var attribute in xmlDocument.Attributes())
    {
        if (!attribute.IsNamespaceDeclaration)
        {
            xElement.Add(attribute);
        }
    }

    return xElement;
}
user2789366
la source
0

Cela a fonctionné pour moi.

       FileStream fs = new FileStream(filePath, FileMode.Open);

       StreamReader sr = new StreamReader(fs);

        DataSet ds = new DataSet();
        ds.ReadXml(sr);
        ds.Namespace = "";

        string outXML = ds.GetXml();
        ds.Dispose();
        sr.Dispose();
        fs.Dispose();
Scott Parker
la source
0

Après avoir beaucoup cherché une solution à ce problème, cette page en particulier semblait avoir le plus de bœuf ... Cependant, rien ne me convenait parfaitement, alors j'ai pris la méthode à l'ancienne et j'ai juste analysé les choses que je voulais. J'espère que cela aide quelqu'un. (Remarque: cela supprime également le SOAP ou tout autre élément d'enveloppe similaire.)

        public static string RemoveNamespaces(string psXml)
    {
        //
        // parse through the passed XML, and remove any and all namespace references...also
        // removes soap envelope/header(s)/body, or any other references via ":" entities,
        // leaving all data intact
        //
        string xsXml = "", xsCurrQtChr = "";
        int xiPos = 0, xiLastPos = psXml.Length - 1;
        bool xbInNode = false;

        while (xiPos <= xiLastPos)
        {
            string xsCurrChr = psXml.Substring(xiPos, 1);
            xiPos++;
            if (xbInNode)
            {
                if (xsCurrChr == ":")
                {
                    // soap envelope or body (or some such)
                    // we'll strip these node wrappers completely
                    // need to first strip the beginning of it off  (i.e. "<soap" or "<s")
                    int xi = xsXml.Length;
                    string xsChr = "";
                    do
                    {
                        xi--;
                        xsChr = xsXml.Substring(xi, 1);
                        xsXml = xsXml.Substring(0, xi);
                    } while (xsChr != "<");

                    // next, find end of node
                    string xsQt = "";
                    do
                    {
                        xiPos++;
                        if (xiPos <= xiLastPos)
                        {
                            xsChr = psXml.Substring(xiPos, 1);
                            if (xsQt.Length == 0)
                            {
                                if (xsChr == "'" || xsChr == "\"")
                                {
                                    xsQt = xsChr;
                                }
                            }
                            else
                            {
                                if (xsChr == xsQt)
                                {
                                    xsQt = "";  // end of quote
                                }
                                else
                                {
                                    if (xsChr == ">") xsChr = "x";      // stay in loop...this is not end of node
                                }
                            }
                        }
                    } while (xsChr != ">" && xiPos <= xiLastPos);
                    xiPos++;            // skip over closing ">"
                    xbInNode = false;
                }
                else
                {
                    if (xsCurrChr == ">")
                    {
                        xbInNode = false;
                        xsXml += xsCurrChr;
                    }
                    else
                    {
                        if (xsCurrChr == " " || xsCurrChr == "\t")
                        {
                            // potential namespace...let's check...next character must be "/"
                            // or more white space, and if not, skip until we find such
                            string xsChr = "";
                            int xiOrgLen = xsXml.Length;
                            xsXml += xsCurrChr;
                            do
                            {
                                if (xiPos <= xiLastPos)
                                {
                                    xsChr = psXml.Substring(xiPos, 1);
                                    xiPos++;
                                    if (xsChr == " " || xsChr == "\r" || xsChr == "\n" || xsChr == "\t")
                                    {
                                        // carry on..white space
                                        xsXml += xsChr;
                                    }
                                    else
                                    {
                                        if (xsChr == "/" || xsChr == ">")
                                        {
                                            xsXml += xsChr;
                                        }
                                        else
                                        {
                                            // namespace! - get rid of it
                                            xsXml = xsXml.Substring(0, xiOrgLen - 0);       // first, truncate any added whitespace
                                            // next, peek forward until we find "/" or ">"
                                            string xsQt = "";
                                            do
                                            {
                                                if (xiPos <= xiLastPos)
                                                {
                                                    xsChr = psXml.Substring(xiPos, 1);
                                                    xiPos++;
                                                    if (xsQt.Length > 0)
                                                    {
                                                        if (xsChr == xsQt) xsQt = ""; else xsChr = "x";
                                                    }
                                                    else
                                                    {
                                                        if (xsChr == "'" || xsChr == "\"") xsQt = xsChr;
                                                    }
                                                }
                                            } while (xsChr != ">" && xsChr != "/" && xiPos <= xiLastPos);
                                            if (xsChr == ">" || xsChr == "/") xsXml += xsChr;
                                            xbInNode = false;
                                        }
                                    }
                                }
                            } while (xsChr != ">" && xsChr != "/" && xiPos <= xiLastPos);
                        }
                        else
                        {
                            xsXml += xsCurrChr;
                        }
                    }
                }
            }
            else
            {
                //
                // if not currently inside a node, then we are in a value (or about to enter a new node)
                //
                xsXml += xsCurrChr;
                if (xsCurrQtChr.Length == 0)
                {
                    if (xsCurrChr == "<")
                    {
                        xbInNode = true;
                    }
                }
                else
                {
                    //
                    // currently inside a quoted string
                    //
                    if (xsCurrQtChr == xsCurrChr)
                    {
                        // finishing quoted string
                        xsCurrQtChr = "";
                    }
                }
            }
        }

        return (xsXml);
    }
LeeT
la source
0

Sans recréer toute la hiérarchie des nœuds:

private static void RemoveDefNamespace(XElement element)
{
    var defNamespase = element.Attribute("xmlns");
    if (defNamespase != null)
        defNamespase.Remove();

    element.Name = element.Name.LocalName;
    foreach (var child in element.Elements())
    {
        RemoveDefNamespace(child);
    }
}
Stas BZ
la source
0

J'ai essayé certaines des solutions, mais comme beaucoup l'ont déclaré, il y a des cas extrêmes.

Utilisé certaines des expressions régulières ci-dessus, mais est arrivé à la conclusion qu'une expression régulière en une étape n'est pas faisable.

Voici donc ma solution, regex en 2 étapes, trouver des balises, supprimer les balises dans les balises, ne pas modifier les cdata:

            Func<Match, String> NamespaceRemover = delegate (Match match)
            {
                var result = match.Value;
                if (String.IsNullOrEmpty(match.Groups["cdata"].Value))
                {
                    // find all prefixes within start-, end tag and attributes and also namespace declarations
                    return Regex.Replace(result, "((?<=<|<\\/| ))\\w+:| xmlns(:\\w+)?=\".*?\"", "");
                }
                else
                {
                    // cdata as is
                    return result;
                }
            };
            // XmlDocument doc;
            // string file;
            doc.LoadXml(
              Regex.Replace(File.ReadAllText(file), 
                // find all begin, cdata and end tags (do not change order)
                @"<(?:\w+:?\w+.*?|(?<cdata>!\[CDATA\[.*?\]\])|\/\w+:?\w+)>", 
                new MatchEvaluator(NamespaceRemover)
              )
            );

Pour l'instant, cela fonctionne à 100% pour moi.

user2056154
la source
-1

Voici une solution basée sur les regex à ce problème ...

    private XmlDocument RemoveNS(XmlDocument doc)
    {
        var xml = doc.OuterXml;
        var newxml = Regex.Replace(xml, @"xmlns[:xsi|:xsd]*="".*?""","");
        var newdoc = new XmlDocument();
        newdoc.LoadXml(newxml);
        return newdoc;
    }
Siddharth
la source
-1

Je pense que c'est la réponse la plus courte (mais pour des constuctions comme, vous aurez une autre discussion, j'ai aussi une expression régulière à convertir "<bcm:info></bcm:info>"en " <info></info>" mais elle n'a pas été optimisée, si quelqu'un me le demande, je la partagerai. Donc, ma solution est:

    public string RemoveAllNamespaces(string xmlDocument)
    {
        return Regex.Replace(xmlDocument, @"\sxmlns(\u003A\w+)?\u003D\u0022.+\u0022", " ");
    }
Léonide
la source