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.
Antworten:
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:
Ich vertrete hier die endgültige saubere und universelle C # -Lösung zum Entfernen von XML-Namespaces:
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.
quelle
Die getaggte nützlichste Antwort weist zwei Mängel auf:
Hier ist meine Meinung dazu:
Beispielcode hier .
quelle
xmlns
.(from a in e.Attributes().DistinctBy(x => x.Name.LocalName)
lang=""ru-ru"" xml:lang=""ru-ru""
die obligatorische Antwort mit LINQ:
quelle
Das wird den Trick machen :-)
quelle
Nehmen Sie es erneut auf, in C # - Zeile zum Kopieren der Attribute hinzugefügt:
quelle
Die obligatorische Antwort mit XSLT:
quelle
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 ...)
quelle
Regex.Replace(xmlStr, @"<(/?)([^>\s:]+):([^>]+)>", "<$1$3>")
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
XmlTextWriter
Klasse 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
Verwendung
quelle
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.
quelle
Mir hat sehr gut gefallen, wohin Dexter dort oben geht, deshalb habe ich es in eine „fließende“ Erweiterungsmethode übersetzt:
Der „fließende“ Ansatz ermöglicht mir Folgendes:
quelle
Sie können dies mit Linq tun:
quelle
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.
quelle
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:
quelle
Etwas spät zur Party, aber hier ist, was ich kürzlich verwendet habe:
(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).
quelle
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:
quelle
Hier ist meine VB.NET-Version der Dexter Legaspi C # -Version
quelle
Eine andere Lösung, die möglicherweise verschachtelte TEXT- und ELEMENT-Knoten berücksichtigt, z.
Code:
quelle
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.)ps, diese spezielle Implementierung verwendet einige .NET 4-Funktionen, um die Implementierung etwas einfacher / sauberer zu machen (Verwendung von
dynamic
und 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.
Und eine kleine Hilfsmethode, um den Ball ins Rollen zu bringen:
Um einen Namespace zu entfernen, können Sie ihn folgendermaßen aufrufen:
Mit diesem Besucher können Sie ein schreiben
INamespaceMappingManager
, um alle Namespaces zu entfernen.quelle
Einfache Lösung, die die Elemente tatsächlich an Ort und Stelle umbenennt, keine Kopie erstellt und die Attribute ziemlich gut ersetzt.
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:
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.
quelle
Durch Hinzufügen von my wird auch der Name von Knoten mit Namespace-Präfixen gelöscht:
quelle
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.
quelle
meine Antwort, String-Manipulation-basierter,
Lite-Most-Code,
quelle
Hier sind Regex Ersetzen Sie einen Liner:
Hier ist ein Beispiel: https://regex101.com/r/fopydN/6
Achtung: Es kann Randfälle geben!
quelle
Die Antwort von user892217 ist fast richtig. Es wird nicht so kompiliert wie es ist, daher muss der rekursive Aufruf leicht korrigiert werden:
quelle
Das hat bei mir funktioniert.
quelle
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.)
quelle
Ohne die gesamte Knotenhierarchie neu zu erstellen:
quelle
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:
Im Moment arbeitet es zu 100% für mich.
quelle
Hier ist eine Regex-basierte Lösung für dieses Problem ...
quelle
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:quelle