Bagaimana cara menghapus semua ruang nama dari XML dengan C #?

104

Saya mencari solusi yang bersih, elegan dan cerdas untuk menghapus namespace dari semua elemen XML? Bagaimana fungsinya untuk melakukan itu?

Antarmuka yang ditentukan:

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

Contoh XML untuk menghapus NS dari:

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

Setelah kita memanggil RemoveAllNamespaces (xmlWithLotOfNs), kita harus mendapatkan:

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

Bahasa solusi yang disukai adalah C # pada .NET 3.5 SP1.

Peter Stegnar
sumber
@ JohnSaunders: Anda benar. Tetapi dalam kasus khusus ini saya harus melakukan beberapa integrasi sistem. Dan ini adalah satu-satunya pilihan saat itu.
Peter Stegnar
@PeterStegnar kesalahan biasanya adalah peretas yang membuat format lama. Seringkali, pengembang menyalahgunakan xml secara kronis. Namespaces adalah fitur gila penting pertama yang harus dikesampingkan.
Gusdor

Jawaban:

103

Nah, inilah jawaban akhirnya. Saya telah menggunakan ide Jimmy yang bagus (yang sayangnya tidak lengkap itu sendiri) dan fungsi rekursi lengkap untuk bekerja dengan baik.

Berdasarkan antarmuka:

string RemoveAllNamespaces(string xmlDocument);

Saya mewakili di sini solusi C # bersih dan universal akhir untuk menghapus ruang nama 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)));
    }

Ini berfungsi 100%, tetapi saya belum banyak mengujinya sehingga mungkin tidak mencakup beberapa kasus khusus ... Tapi itu dasar yang baik untuk memulai.

Peter Stegnar
sumber
8
Seberapa baik cara kerjanya dengan atribut yang memiliki ruang nama? Faktanya, kode Anda mengabaikan atribut sepenuhnya.
John Saunders
6
Saya menyadari ruang nama mungkin berguna dalam beberapa aplikasi, tetapi tidak sama sekali di aplikasi saya; mereka menyebabkan gangguan besar. Solusi ini berhasil untuk saya.
JYelton
@ John Saunders - Ya, saya menggunakan solusi itu dan saya menyadari bahwa Anda benar. Saya memposting solusi yang diperbarui sebagai jawaban
Konrad Morawski
6
Solusi ini TIDAK berhasil untuk saya, karena kode menghapus semua atribut serta ruang nama. Tentu saja, beberapa perubahan mungkin berhasil untuk melihat apakah atribut yang dihapus adalah namespace atau atribut
bigfoot
@KonradMorawski, sayangnya, saya tidak melihat jawaban Anda di sini. :(
Rami A.
63

Jawaban paling berguna yang diberi tag memiliki dua kekurangan:

  • Ini mengabaikan atribut
  • Ini tidak bekerja dengan elemen "mode campuran"

Inilah pendapat saya tentang ini:

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

Kode contoh di sini .

Dexter Legaspi
sumber
Sayangnya, ini tidak berhasil untuk saya, xml yang sama yang dimasukkan dikembalikan. :(
Rami A.
@Rami. dapatkah Anda memposting potongan kode sehingga kami dapat melihat apa masalahnya?
Dexter Legaspi
Juga tidak berhasil untuk saya. Saya kira karena Anda menyalin atribut, Anda juga menyalinnya xmlns.
MarioDS
1
Ini bekerja. Saya telah menggunakannya ... namun saya menyadari itu tidak pembersihan menyeluruh dalam arti bahwa itu tidak menghapus atribut xmlns sebenarnya yang menentukan namespace ... jadi saya memperbaruinya untuk melakukan hal itu ... dan menambahkan contoh inti .
Dexter Legaspi
Perlu ditambahkan (from a in e.Attributes().DistinctBy(x => x.Name.LocalName)untuk kasuslang=""ru-ru"" xml:lang=""ru-ru""
smg
26

jawaban wajib menggunakan 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
sumber
3
Saya kira Anda dapat menunjukkan kepada orang-orang VB bahwa Anda dapat memiliki literal XML dalam C #.
Robert Harvey
1
@ Robert, itu bukan literal XML. Itu string. Ada perbedaan besar!
CoderDennis
Jimmy, kamu dekat tapi belum sampai. :) Saya menulis solusi akhir berdasarkan ide Anda. Saya akan posting di sana.
Peter Stegnar
Anda benar :) sementara Anda melakukannya, saya menawarkan perbaikan versi saya sendiri.
Jimmy
3
Ini menghapus semua atribut, bukan hanya namespace. Lihat jawaban florian untuk perbaikan.
Brian
25

Itu akan berhasil :-)

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
sumber
Yo ini berfungsi dengan baik, tidak hanya berfungsi, itu bahkan tidak mempengaruhi file itu menulis data juga Xelement menggunakan metode DescendantAndself. Terima kasih sobat!
shawn
bekerja untuk saya. Juga menangani CDATA yang solusi lain longgar di sepanjang jalan.
paul
16

Ambil lagi, di C # - baris ditambahkan untuk menyalin atribut:

    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
sumber
1
Bekerja untuk elemen root, tetapi tidak untuk elemen bertingkat; namespace tampaknya baru saja diganti, mungkin secara otomatis oleh XElement.ToString ().
Rami A.
Persis yang saya butuhkan untuk menghapus semua ruang nama, tetapi tetap mempertahankan atribut.
Bassie
10

Jawaban wajib menggunakan 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
sumber
1 untuk "wajib". :-) Saya masih bertanya-tanya mengapa menghapus namespace akan menjadi keputusan yang cerdas. Ini mungkin macet dan terbakar pada <element ns: attr = "a" attr = "b" />.
Tomalak
Oh tentu, tetapi setiap teknik penghilangan NS akan lebih atau kurang. Sebagai atau validitas, saya dapat memberi tahu Anda di mana saya membutuhkannya: mengimpor XML pihak ketiga di mana mereka tidak dapat memilah XSD yang valid tetapi bersikeras pada namespacing. Aturan kepraktisan pada akhirnya.
annakata
1
@annakata: Solusinya lebih sederhana dari yang Anda pikirkan. Berhenti mengaktifkan. Menolak untuk menggunakan teknik apa pun yang tidak memahami XML. Satu-satunya alasan kami masih terpaksa menggunakan sampah semacam itu adalah karena orang-orang terus berkata, "ya", ketika mereka perlu mengatakan "tidak" lebih sering. Standarnya sudah lebih dari 10 tahun! Mengapa lagi kita masih memiliki perangkat lunak yang tidak memahami XML Namespaces, kecuali bahwa kita terus mengaktifkannya?
John Saunders
3
@John - ha, ada hal-hal yang harus dilakukan, dan ada hal-hal yang dianggap manajemen akan selesai. Semuanya adalah untuk yang terbaik dari yang terbaik dari semua kemungkinan dunia.
annakata
1
@Tomalak satu kasus penggunaan mungkin jika Anda perlu mengonversi ke JSON dan deklarasi namespace mengganggu proses itu.
devlord
10

Dan ini adalah solusi sempurna yang juga akan menghapus elemen XSI. (Jika Anda menghapus xmlns dan tidak menghapus XSI, .Net berteriak pada Anda ...)

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
sumber
1
Saya harus membaca ini 2 jam yang lalu. Melakukan regex yang hampir sama, satu-satunya yang berfungsi, dalam XML yang kompleks, dengan banyak namespace, atribut, dll.
TPAKTOPA
Perlu diingat bahwa Anda mungkin masih harus membersihkan elemen seperti misalnya <xxx: tagname>. Saya menggunakan kode berikut (disclaimer, berfungsi pada mesin saya): Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
Edwin
9

Saya tahu pertanyaan ini seharusnya diselesaikan, tetapi saya tidak sepenuhnya senang dengan cara penerapannya. Saya menemukan sumber lain di sini di blog MSDN yang memiliki XmlTextWriterkelas yang diganti yang menghapus ruang nama. Saya sedikit men-tweaknya untuk mendapatkan beberapa hal lain yang saya inginkan seperti pemformatan yang cantik dan mempertahankan elemen root. Inilah yang saya miliki dalam proyek saya saat ini.

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

Kelas

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

Pemakaian

//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);
}
bercanda
sumber
1
Jawaban Anda adalah satu-satunya yang tidak terasa seperti hack, namun, contoh asli dalam posting blog yang direferensikan lebih tepat karena jika Anda tidak menghapus namespace di node root, maka semua node dan atribut turunan tanpa namespace akan mewarisi namespace root.
tenor
8

Ini adalah solusi berdasarkan jawaban yang diterima Peter Stegnar.

Saya menggunakannya, tetapi (seperti yang dikatakan andygjp dan John Saunders) kodenya mengabaikan atribut .

Saya perlu menjaga atribut juga, jadi saya menyesuaikan kodenya. Versi Andy adalah Visual Basic, ini masih c #.

Saya tahu ini sudah lama, tetapi mungkin itu akan menghemat waktu seseorang suatu hari nanti.

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

Saya sangat menyukai tujuan Dexter di sana, jadi saya menerjemahkannya ke dalam metode ekstensi yang "lancar":

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

Pendekatan "lancar" memungkinkan saya melakukan ini:

var xml = File.ReadAllText(presentationFile);
var xDoc = XDocument.Parse(xml);
var xRoot = xDoc.Root.WithoutNamespaces();
rasx
sumber
1
Terima kasih untuk solusi ini! Berfungsi bagus untuk masalah saya.
AngieM
1
Jadi ini ideal KARENA bekerja pada atribut. Bisa menggunakan ini tanpa masalah. Terima kasih
julian guppy
4

Anda dapat melakukannya dengan menggunakan 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
sumber
3

Jawaban Peter yang sedikit dimodifikasi, ini akan berfungsi dengan baik untuk atribut juga, termasuk menghapus namespace dan awalan. Sedikit maaf karena kodenya terlihat agak jelek.

 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
sumber
+1 Ini berhasil untuk saya. Namun, ia meninggalkan atribut yang merupakan bagian dari definisi namespace (hanya awalan xmlns yang dihapus) tetapi saat ini mereka tidak memengaruhi serialisasi.
Rami A.
2

Balasan oleh Jimmy dan Peter sangat membantu, tetapi mereka benar-benar menghapus semua atribut, jadi saya membuat sedikit modifikasi:

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

Agak terlambat ke pesta yang satu ini tapi inilah yang saya gunakan baru-baru ini:

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

(diambil dari Thread MSDN ini )

Sunting Sesuai komentar di bawah ini, tampaknya sementara ini menghapus awalan namespace dari node itu tidak benar-benar menghapus atribut xmlns. Untuk melakukan itu Anda juga perlu mengatur ulang nama setiap node ke nama lokalnya (misalnya nama minus namespace)

foreach (var node in doc.Root.DescendantNodesAndSelf().OfType<XElement>())
{
    node.Name = node.Name.LocalName;
}
MarcE
sumber
Sepertinya tidak berhasil? Ia menemukan semua deklarasi namespace, tetapi memanggil Remove () pada koleksi itu tidak melakukan apa-apa. Saya mencoba result.ToString (), dan string yang dihasilkan masih memiliki atribut xmlns. Apakah saya melakukan sesuatu yang salah?
Jimmy
Ini bekerja untuk apa yang saya butuhkan pada saat itu tetapi sekarang saya melihat kembali itu tidak 100%. Itu menghapus awalan namespace dari node (yang saya butuhkan) tetapi Anda benar tentang itu meninggalkan atribut xmlns di belakang. Anehnya, atribut itu juga tidak dikenali oleh salah satu metode XDocument!
MarcE
1

Agar atribut bekerja, loop for untuk menambahkan atribut harus pergi setelah rekursi, juga perlu memeriksa apakah 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;
}
pengguna892217
sumber
1

Ini adalah versi VB.NET saya dari 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
pengguna2740574
sumber
1

Solusi lain yang memperhitungkan kemungkinan interleaving node TEXT dan ELEMENT, misalnya:

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

Kode:

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;
        }
    }
}
esteewhy
sumber
1

Tanpa menggunakan solusi berbasis XSLT, jika Anda ingin bersih, elegan, dan cerdas, Anda memerlukan dukungan dari kerangka kerja, khususnya, pola pengunjung dapat membuat ini mudah. Sayangnya, tidak tersedia di sini.

Saya telah menerapkannya terinspirasi oleh LINQ ExpressionVisitoruntuk memiliki struktur yang mirip dengannya. Dengan ini, Anda dapat menerapkan pola pengunjung ke objek XML (LINQ-to-). (Saya telah melakukan pengujian terbatas pada ini tetapi sejauh yang saya tahu berhasil dengan baik)

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, implementasi khusus ini menggunakan beberapa fitur .NET 4 untuk membuat implementasi sedikit lebih mudah / lebih bersih (penggunaan dynamicdan argumen default). Seharusnya tidak terlalu sulit untuk membuatnya kompatibel dengan .NET 3.5, bahkan mungkin kompatibel dengan .NET 2.0.

Kemudian untuk mengimplementasikan pengunjung, berikut adalah cara umum yang dapat mengubah beberapa ruang nama (dan awalan yang digunakan).

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

Dan sedikit metode penolong untuk membuat bola bergulir:

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

Kemudian untuk menghapus namespace, Anda bisa menyebutnya seperti ini:

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

Menggunakan pengunjung ini, Anda dapat menulis INamespaceMappingManageruntuk menghapus semua ruang nama.

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

Solusi sederhana yang benar-benar mengganti nama elemen di tempat, bukan membuat salinan, dan melakukan pekerjaan yang cukup baik dalam mengganti atribut.

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

Catatan: ini tidak selalu mempertahankan urutan atribut asli, tetapi saya yakin Anda dapat mengubahnya untuk melakukannya dengan mudah jika itu penting bagi Anda.

Perhatikan juga bahwa ini juga dapat memunculkan pengecualian, jika Anda memiliki atribut XElement yang hanya unik dengan namespace, seperti:

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

yang sepertinya merupakan masalah yang melekat. Tetapi karena pertanyaan menunjukkan mengeluarkan String, bukan XElement, dalam hal ini Anda dapat memiliki solusi yang akan menghasilkan String valid yang merupakan XElement yang tidak valid.

Saya juga menyukai jawaban jocull menggunakan XmlWriter kustom, tetapi ketika saya mencobanya, itu tidak berhasil untuk saya. Meskipun semuanya terlihat benar, saya tidak tahu apakah kelas XmlNoNamespaceWriter berpengaruh sama sekali; itu pasti tidak menghapus ruang nama seperti yang saya inginkan.

Sempoa
sumber
1

Menambahkan my that juga membersihkan nama node yang memiliki prefiks namespace:

    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;
    }
Serigala5
sumber
1

Saya mencoba beberapa solusi pertama dan tidak berhasil untuk saya. Terutama masalah dengan atribut yang dihapus seperti yang telah disebutkan sebelumnya. Saya akan mengatakan pendekatan saya sangat mirip dengan Jimmy dengan menggunakan konstruktor XElement yang mengambil objek sebagai parameter.

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

jawaban saya,
kode berbasis manipulasi string, kode paling ringan,

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

Berikut adalah Regex Replace one liner:

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

Berikut contohnya: https://regex101.com/r/fopydN/6

Peringatan: mungkin ada casing edge!

Visar
sumber
0

Jawaban user892217 hampir benar. Itu tidak akan dikompilasi apa adanya, jadi perlu sedikit koreksi pada panggilan rekursif:

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;
}
pengguna2789366
sumber
0

Ini berhasil untuk saya.

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

Setelah banyak mencari solusi untuk masalah ini, halaman khusus ini tampaknya memiliki daging paling banyak ... namun, tidak ada yang benar-benar cocok, jadi saya mengambil cara kuno dan hanya menguraikan hal-hal yang saya inginkan. Semoga ini bisa membantu seseorang. (Catatan: ini juga menghapus SOAP atau barang amplop serupa.)

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

Tanpa membuat ulang seluruh hierarki node:

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

Saya mencoba beberapa solusi, tetapi seperti yang dinyatakan oleh begitu banyak, ada beberapa kasus tepi.

Menggunakan beberapa regex di atas, tetapi sampai pada kesimpulan bahwa regex satu langkah tidak dapat dibuat.

Jadi inilah solusi saya, 2 langkah regex, temukan tag, di dalam tag hapus, jangan ubah 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)
              )
            );

Untuk saat ini 100% berhasil untuk saya.

pengguna2056154
sumber
-1

Berikut adalah solusi berbasis regex untuk masalah ini ...

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

Saya pikir ini adalah jawaban terpendek (tetapi untuk konstruksi seperti, Anda akan berdiskusi lagi, saya juga memiliki regex untuk diubah "<bcm:info></bcm:info>"menjadi " <info></info>" tetapi itu tidak dioptimalkan, Jika seseorang bertanya kepada saya, saya akan membagikannya. Jadi, solusi saya adalah:

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