Ich analysiere einige XML-Dateien von einem Drittanbieter und leider ist es nicht immer wohlgeformtes XML, da manchmal einige Elemente doppelte Attribute enthalten.
Ich habe keine Kontrolle über die Quelle und ich weiß nicht, welche Elemente doppelte Attribute haben, noch kenne ich die doppelten Attributnamen im Voraus.
Offensichtlich löst das Laden des Inhalts in ein XMLDocument
Objekt eine XmlException für die doppelten Attribute aus, so dass ich einen XmlReader
, um das XML-Element XmlReader
und mit den doppelten Attributen XmlReader
zu werden, wenn ich zu dem fehlerhaften Element komme.
Die XmlException
wird jedoch in reader.Read()
bevor ich die Attribute des Elements erkennen kann.
Hier ist eine Beispielmethode, um das Problem zu demonstrieren:
public static void ParseTest()
{
const string xmlString =
@"<?xml version='1.0'?>
<!-- This is a sample XML document -->
<Items dupattr=""10"" id=""20"" dupattr=""33"">
<Item>test with a child element <more/> stuff</Item>
</Items>";
var output = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
XmlWriterSettings ws = new XmlWriterSettings();
ws.Indent = true;
using (XmlWriter writer = XmlWriter.Create(output, ws))
{
while (reader.Read()) /* Exception throw here when Items element encountered */
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
writer.WriteStartElement(reader.Name);
if (reader.HasAttributes){ /* CopyNonDuplicateAttributes(); */}
break;
case XmlNodeType.Text:
writer.WriteString(reader.Value);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
writer.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
writer.WriteComment(reader.Value);
break;
case XmlNodeType.EndElement:
writer.WriteFullEndElement();
break;
}
}
}
}
string str = output.ToString();
}
Gibt es eine andere Möglichkeit, die Eingabe zu analysieren und die doppelten Attribute zu entfernen, ohne reguläre Ausdrücke und Zeichenfolgenmanipulation zu verwenden?
Ich fand eine Lösung, indem ich XML als HTML-Dokument betrachtete. Dann konnte ich mithilfe der Open-Source- HTML-Agility-Pack- Bibliothek gültige XML- Dateien abrufen .
Der Trick bestand darin, das XML zuerst mit einem HTML-Header zu speichern.
Ersetzen Sie die XML-Deklaration
<?xml version="1.0" encoding="utf-8" ?>
mit einer HTML-Deklaration wie folgt:
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Sobald der Inhalt in einer Datei gespeichert wurde, gibt diese Methode ein gültiges XML-Dokument zurück.
// Requires reference to HtmlAgilityPack
public XmlDocument LoadHtmlAsXml(string url)
{
var web = new HtmlWeb();
var m = new MemoryStream();
var xtw = new XmlTextWriter(m, null);
// Load the content into the writer
web.LoadHtmlAsXml(url, xtw);
// Rewind the memory stream
m.Position = 0;
// Create, fill, and return the xml document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml((new StreamReader(m)).ReadToEnd());
return xmlDoc;
}
Die doppelten Attributknoten werden automatisch mit den späteren Attributwerten entfernt, wobei die früheren überschrieben werden.
Ok, denke du musst den Fehler abfangen:
Dann sollten Sie die folgenden Methoden verwenden können:
reader.MoveToFirstAttribute();
und
reader.MoveToNextAttribute()
um die folgenden Eigenschaften zu erhalten:
reader.Value
reader.Name
Dadurch können Sie alle Attributwerte abrufen.