Wie entferne ich alle Namespaces mit C # aus XML?

104

Ich suche nach einer sauberen, eleganten und intelligenten Lösung, um Namespace-Bereiche aus allen XML-Elementen zu entfernen. Wie würde das funktionieren?

Definierte Schnittstelle:

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

Beispiel-XML zum Entfernen von NS aus:

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

Nachdem wir RemoveAllNamespaces (xmlWithLotOfNs) aufgerufen haben, sollten wir Folgendes erhalten:

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

Bevorzugte Lösungssprache ist C # unter .NET 3.5 SP1.

Peter Stegnar
quelle
@ JohnSaunders: Du hast recht. Aber in diesem speziellen Fall muss ich eine Systemintegration durchführen. Und das war damals die einzige Option.
Peter Stegnar
@PeterStegnar Der Fehler ist normalerweise der Hacker, der die Legacy-Formate erstellt hat. Oft missbrauchen Entwickler XML chronisch. Namespaces sind das erste verrückte wichtige Feature, das beiseite geworfen wird.
Gusdor

Antworten:

103

Hier ist die endgültige Antwort. Ich habe eine großartige Jimmy-Idee (die leider nicht vollständig ist) und eine vollständige Rekursionsfunktion verwendet, um richtig zu funktionieren.

Basierend auf der Schnittstelle:

string RemoveAllNamespaces(string xmlDocument);

Ich vertrete hier die endgültige saubere und universelle C # -Lösung zum Entfernen von XML-Namespaces:

//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)));
    }

Es funktioniert zu 100%, aber ich habe es nicht viel getestet, so dass es möglicherweise einige Sonderfälle nicht abdeckt ... Aber es ist eine gute Basis, um anzufangen.

Peter Stegnar
quelle
8
Wie gut funktioniert das mit Attributen mit Namespaces? Tatsächlich ignoriert Ihr Code Attribute nur vollständig.
John Saunders
6
Mir ist klar, dass Namespaces in einigen Anwendungen nützlich sein können, in meinen jedoch überhaupt nicht. Sie verursachten einen großen Ärger. Diese Lösung hat bei mir funktioniert.
JYelton
@ John Saunders - Ja, ich habe diese Lösung verwendet und festgestellt, dass Sie Recht hatten. Ich poste eine aktualisierte Lösung als Antwort
Konrad Morawski
6
Diese Lösung hat bei mir NICHT funktioniert, da der Code alle Attribute sowie die Namespaces entfernt. Natürlich könnten einige Änderungen funktionieren, um festzustellen, ob das zu entfernende Attribut ein Namespace oder ein Attribut ist
Bigfoot
@KonradMorawski, leider sehe ich deine Antwort hier nicht. :(
Rami A.
63

Die getaggte nützlichste Antwort weist zwei Mängel auf:

  • Attribute werden ignoriert
  • Es funktioniert nicht mit "Mixed Mode" -Elementen

Hier ist meine Meinung dazu:

 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);
  }          

Beispielcode hier .

Dexter Legaspi
quelle
Leider hat dies bei mir nicht funktioniert, die gleiche eingegebene XML wurde zurückgegeben. :(
Rami A.
@ RamiA. Können Sie einen Ausschnitt aus dem Code veröffentlichen, damit wir sehen können, wo das Problem liegt?
Dexter Legaspi
Hat auch bei mir nicht funktioniert. Ich denke, da Sie die Attribute kopieren, kopieren Sie auch einfach die xmlns.
MarioDS
1
Das funktioniert. Ich habe es verwendet ... aber ich habe festgestellt, dass es keine gründliche Reinigung in dem Sinne ist, dass es nicht die tatsächlichen xmlns-Attribute entfernt, die den Namespace definieren ... also habe ich es aktualisiert, um genau das zu tun ... und ein grundlegendes Beispiel hinzugefügt .
Dexter Legaspi
(from a in e.Attributes().DistinctBy(x => x.Name.LocalName)lang=""ru-ru"" xml:lang=""ru-ru""
Müssen
26

die obligatorische Antwort mit 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
quelle
3
Ich denke, Sie können den VB-Leuten zeigen, dass Sie doch ein XML-Literal in C # haben können.
Robert Harvey
1
@ Robert, das ist kein XML-Literal. Es ist eine Schnur. Es gibt einen großen Unterschied!
CoderDennis
Jimmy, du bist nah dran, aber noch nicht da. :) Ich schreibe eine endgültige Lösung basierend auf Ihrer Idee. Ich werde es dort posten.
Peter Stegnar
du hast recht :) während du dabei bist, biete ich meine eigene Version des Fixes an.
Jimmy
3
Dadurch werden alle Attribute entfernt, nicht nur Namespaces. Siehe Florians Antwort zur Behebung.
Brian
25

Das wird den Trick machen :-)

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
quelle
Dies funktioniert hervorragend, es funktioniert nicht nur, es wirkt sich auch nicht auf die Datei aus, in der die Daten mithilfe der DescendantAndself-Methode auf das Xelement geschrieben werden. Danke, Mann!
Shawn
funktioniert bei mir. Behandelt auch CDATA, die andere Lösungen auf dem Weg verlieren.
Paul
16

Nehmen Sie es erneut auf, in C # - Zeile zum Kopieren der Attribute hinzugefügt:

    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
quelle
1
Funktioniert für das Stammelement, jedoch nicht für verschachtelte Elemente. Die Namespaces scheinen nur umbenannt zu werden, möglicherweise automatisch von XElement.ToString ().
Rami A.
Genau das, was ich brauchte, um alle Namespaces zu entfernen, aber Attribute beizubehalten.
Bassie
10

Die obligatorische Antwort mit 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
quelle
+1 für die "obligatorische". :-) Ich frage mich immer noch, warum das Entfernen von Namespaces eine kluge Entscheidung wäre. Dies stürzt wahrscheinlich ab und brennt auf <element ns: attr = "a" attr = "b" />.
Tomalak
Sicher, aber jede NS-Entfernungstechnik wird mehr oder weniger gut funktionieren. Als oder Gültigkeit kann ich Ihnen sagen, wo ich es gebraucht habe: Importieren von XML von Drittanbietern, wo sie keine gültige XSD aussortieren können, sondern auf Namespace bestehen. Praktikabilität regiert letztendlich.
Annakata
1
@annakata: Die Lösung ist einfacher als Sie denken. Stoppen Sie die Aktivierung. Verweigern Sie die Verwendung von Techniken, die XML nicht verstehen. Der einzige Grund, warum wir immer noch gezwungen sind, solchen Müll zu verwenden, ist, dass die Leute immer wieder "Ja" sagen, wenn sie etwas öfter "Nein" sagen müssen. Die Standards sind über 10 Jahre alt! Warum haben wir sonst noch Software, die XML-Namespaces nicht versteht, außer dass wir sie weiterhin aktivieren?
John Saunders
3
@ John - ha, es gibt die Dinge, die getan werden sollten, und es gibt die Dinge, die das Management für erledigt hält. Alles ist zum Besten in der besten aller möglichen Welten.
Annakata
1
@Tomalak Ein Anwendungsfall könnte sein, wenn Sie in JSON konvertieren müssen und Namespace-Deklarationen diesen Prozess stören.
Devlord
10

Und dies ist die perfekte Lösung, um auch XSI-Elemente zu entfernen. (Wenn Sie die XML-Dateien entfernen und XSI nicht entfernen, schreit .Net Sie an ...)

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
quelle
1
Ich sollte das vor 2 Stunden lesen. Hat fast den gleichen regulären Ausdruck gemacht, das einzige, was in komplexem XML mit vielen Namespaces, Attributen usw.
funktioniert hat
Denken Sie daran, dass Sie möglicherweise noch Elemente wie z. B. <xxx: tagname> bereinigen müssen. Ich habe folgenden Code verwendet (Haftungsausschluss, funktioniert auf meinem Computer): Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Edwin
9

Ich weiß, dass diese Frage angeblich gelöst ist, aber ich war nicht ganz zufrieden mit der Art und Weise, wie sie implementiert wurde. Ich habe hier in den MSDN-Blogs eine andere Quelle gefunden, die eine überschriebene XmlTextWriterKlasse hat, die die Namespaces entfernt. Ich habe es ein wenig optimiert, um einige andere Dinge zu bekommen, die ich wollte, wie hübsche Formatierung und Beibehaltung des Stammelements. Folgendes habe ich momentan in meinem Projekt.

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

Klasse

/// <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);
    }
}

Verwendung

//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);
}
scherz
quelle
1
Ihre Antwort ist die einzige, die sich nicht wie ein Hack anfühlt. Das Originalbeispiel im referenzierten Blog-Beitrag ist jedoch korrekter, denn wenn Sie den Namespace im Stammknoten nicht entfernen, sind alle untergeordneten Knoten und Attribute ohne a Der Namespace erbt den Root-Namespace.
Tenor
8

Dies ist eine Lösung, die auf der akzeptierten Antwort von Peter Stegnar basiert.

Ich habe es benutzt, aber (wie andygjp und John Saunders bemerkten) ignoriert sein Code Attribute .

Ich musste mich auch um Attribute kümmern, also habe ich seinen Code angepasst. Andys Version war Visual Basic, dies ist immer noch c #.

Ich weiß, dass es eine Weile her ist, aber vielleicht spart es jemandem eines Tages etwas Zeit.

    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
quelle
6

Mir hat sehr gut gefallen, wohin Dexter dort oben geht, deshalb habe ich es in eine „fließende“ Erweiterungsmethode übersetzt:

/// <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));
}

Der „fließende“ Ansatz ermöglicht mir Folgendes:

var xml = File.ReadAllText(presentationFile);
var xDoc = XDocument.Parse(xml);
var xRoot = xDoc.Root.WithoutNamespaces();
rasx
quelle
1
Danke für diese Lösung! Funktioniert hervorragend für mein Problem.
AngieM
1
Das war also ideal, weil es an den Attributen funktionierte. Konnte dies problemlos nutzen. Vielen Dank
Julian Guppy
4

Sie können dies mit Linq tun:

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
quelle
3

Die Antwort von Peter wurde leicht geändert, dies würde auch für das Attribut gut funktionieren, einschließlich des Entfernens des Namespace und des Präfixes. Ein bisschen Entschuldigung für den Code sieht ein bisschen hässlich aus.

 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
quelle
+1 Das hat bei mir funktioniert. Es bleiben jedoch Attribute übrig, die Teil der Namespace-Definition waren (nur das XML-Präfix wurde entfernt), aber sie wirken sich derzeit nicht auf die Serialisierung aus.
Rami A.
2

Die Antworten von Jimmy und Peter waren eine große Hilfe, aber sie haben tatsächlich alle Attribute entfernt, also habe ich eine kleine Änderung vorgenommen:

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
quelle
2

Etwas spät zur Party, aber hier ist, was ich kürzlich verwendet habe:

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

(aus diesem MSDN-Thread entnommen )

Bearbeiten Gemäß dem folgenden Kommentar scheint das Namespace-Präfix zwar von den Knoten entfernt zu werden, das xmlns-Attribut jedoch nicht. Dazu müssen Sie auch den Namen jedes Knotens auf seinen lokalen Namen zurücksetzen (z. B. Name minus Namespace).

foreach (var node in doc.Root.DescendantNodesAndSelf().OfType<XElement>())
{
    node.Name = node.Name.LocalName;
}
MarcE
quelle
Scheint nicht zu funktionieren? Es werden alle Namespace-Deklarationen gefunden, aber das Aufrufen von Remove () für diese Auflistung führt zu nichts. Ich habe result.ToString () ausprobiert, und die resultierende Zeichenfolge hat immer noch das Attribut xmlns. Mache ich etwas falsch?
Jimmy
Es hat für das funktioniert, was ich damals brauchte, aber jetzt schaue ich zurück, es ist nicht 100%. Es entfernt zwar die Namespace-Präfixe von den Knoten (was ich brauchte), aber Sie haben Recht damit, das xmlns-Attribut zurückzulassen. Seltsamerweise wird dieses Attribut auch von keiner der XDocument-Methoden erkannt!
MarcE
1

Damit Attribute funktionieren, sollte die for-Schleife zum Hinzufügen von Attributen nach der Rekursion ausgeführt werden. Außerdem muss überprüft werden, ob 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
quelle
1

Hier ist meine VB.NET-Version der Dexter Legaspi C # -Version

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
quelle
1

Eine andere Lösung, die möglicherweise verschachtelte TEXT- und ELEMENT-Knoten berücksichtigt, z.

<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;
        }
    }
}
Wertschätzung
quelle
1

Ohne auf eine XSLT-basierte Lösung zurückzugreifen, benötigen Sie, wenn Sie sauber, elegant und intelligent sein möchten, Unterstützung durch das Framework. Insbesondere das Besuchermuster könnte dies zu einem Kinderspiel machen. Leider ist es hier nicht verfügbar.

Ich habe es inspiriert von LINQs implementiert ExpressionVisitor, um eine ähnliche Struktur zu haben. Mit dieser Option können Sie das Besuchermuster auf (LINQ-to-) XML-Objekte anwenden. (Ich habe nur begrenzte Tests durchgeführt, aber es funktioniert gut, soweit ich das beurteilen kann.)

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, diese spezielle Implementierung verwendet einige .NET 4-Funktionen, um die Implementierung etwas einfacher / sauberer zu machen (Verwendung von dynamicund Standardargumente). Es sollte nicht zu schwierig sein, .NET 3.5-kompatibel zu machen, vielleicht sogar .NET 2.0-kompatibel.

Um den Besucher zu implementieren, folgt ein allgemeiner, der mehrere Namespaces (und das verwendete Präfix) ändern kann.

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);
}

Und eine kleine Hilfsmethode, um den Ball ins Rollen zu bringen:

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;
}

Um einen Namespace zu entfernen, können Sie ihn folgendermaßen aufrufen:

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

Mit diesem Besucher können Sie ein schreiben INamespaceMappingManager, um alle Namespaces zu entfernen.

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
quelle
1

Einfache Lösung, die die Elemente tatsächlich an Ort und Stelle umbenennt, keine Kopie erstellt und die Attribute ziemlich gut ersetzt.

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();
  }
}

Hinweis: Dadurch wird nicht immer die ursprüngliche Attributreihenfolge beibehalten, aber ich bin sicher, dass Sie dies ändern können, wenn dies für Sie wichtig ist.

Beachten Sie auch , dass dies auch könnte eine Ausnahme auslösen, wenn Sie ein XElement Attribut haben , die nur einmalig mit dem Namespace ist, wie:

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

Das scheint wirklich ein inhärentes Problem zu sein. Da die Frage jedoch die Ausgabe eines Strings und nicht eines XElement anzeigte, könnten Sie in diesem Fall eine Lösung haben, die einen gültigen String ausgibt, der ein ungültiges XElement ist.

Ich mochte auch die Antwort von jocull mit einem benutzerdefinierten XmlWriter, aber als ich es versuchte, funktionierte es bei mir nicht. Obwohl alles korrekt aussieht , konnte ich nicht sagen, ob die XmlNoNamespaceWriter-Klasse überhaupt einen Effekt hatte. Es wurde definitiv nicht die Namespaces entfernt, wie ich es wollte.

Abakus
quelle
1

Durch Hinzufügen von my wird auch der Name von Knoten mit Namespace-Präfixen gelöscht:

    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;
    }
Wolf5
quelle
1

Ich habe die ersten Lösungen ausprobiert und bei mir nicht funktioniert. Hauptsächlich das Problem mit Attributen, die wie die anderen entfernt wurden, wurde bereits erwähnt. Ich würde sagen, mein Ansatz ist Jimmy sehr ähnlich, indem ich die XElement-Konstruktoren verwende, die Objekte als Parameter verwenden.

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
quelle
1

meine Antwort, String-Manipulation-basierter,
Lite-Most-Code,

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
quelle
1

Hier sind Regex Ersetzen Sie einen Liner:

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

Hier ist ein Beispiel: https://regex101.com/r/fopydN/6

Achtung: Es kann Randfälle geben!

Visar
quelle
0

Die Antwort von user892217 ist fast richtig. Es wird nicht so kompiliert wie es ist, daher muss der rekursive Aufruf leicht korrigiert werden:

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
quelle
0

Das hat bei mir funktioniert.

       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
quelle
0

Nachdem ich viel nach einer Lösung für dieses Problem gesucht hatte, schien diese bestimmte Seite das meiste Rindfleisch zu haben ... jedoch passte nichts genau, also nahm ich den altmodischen Weg und analysierte einfach das Zeug, das ich heraus wollte. Hoffe das hilft jemandem. (Hinweis: Dadurch werden auch die SOAP oder ähnliche Umschläge entfernt.)

        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
quelle
0

Ohne die gesamte Knotenhierarchie neu zu erstellen:

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
quelle
0

Ich habe einige der Lösungen ausprobiert, aber wie von so vielen angegeben, gibt es einige Randfälle.

Verwendete einige der oben genannten regulären Ausdrücke, kam jedoch zu dem Schluss, dass eine einstufige Regex nicht durchführbar ist.

Also hier ist meine Lösung, 2-Schritt-Regex, Tags finden, innerhalb von Tags entfernen, CD-Daten nicht ändern:

            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)
              )
            );

Im Moment arbeitet es zu 100% für mich.

user2056154
quelle
-1

Hier ist eine Regex-basierte Lösung für dieses Problem ...

    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
quelle
-1

Ich denke, dies ist die kürzeste Antwort (aber für Konstruktionen wie, Sie werden eine weitere Diskussion haben, ich muss auch Regex in "<bcm:info></bcm:info>"" <info></info>" konvertieren , aber es wurde nicht optimiert. Wenn mich jemand fragt, werde ich es teilen. Meine Lösung lautet also:

    public string RemoveAllNamespaces(string xmlDocument)
    {
        return Regex.Replace(xmlDocument, @"\sxmlns(\u003A\w+)?\u003D\u0022.+\u0022", " ");
    }
Leonid
quelle