xml.LoadData - Daten auf Stammebene sind ungültig. Zeile 1, Position 1

76

Ich versuche, XML in einem WiX-Installationsprogramm zu analysieren. Das XML wäre ein Objekt aller meiner Fehler, die von einem Webserver zurückgegeben wurden. Ich erhalte den Fehler im Fragentitel mit diesem Code:

XmlDocument xml = new XmlDocument();
try
{
    xml.LoadXml(myString);
}
catch (Exception ex)
{
    System.IO.File.WriteAllText(@"C:\text.txt", myString + "\r\n\r\n" + ex.Message);
    throw ex;
}

myStringist dies (wie in der Ausgabe von gesehen text.txt)

<?xml version="1.0" encoding="utf-8"?>
<Errors></Errors>

text.txt kommt so aus:

<?xml version="1.0" encoding="utf-8"?>
<Errors></Errors>

Data at the root level is invalid. Line 1, position 1.

Ich benötige dieses XML zum Parsen, damit ich sehen kann, ob ich Fehler hatte.

Bearbeiten

Diese Frage ist kein Duplikat wie markiert. In dieser Frage hat die Person, die die Frage gestellt hat LoadXml, eine XML-Datei analysiert. Ich analysiere einen String, der die richtige Verwendung von istLoadXml

Chris
quelle
Müsste wirklich die XML sehen, um zu helfen
RedEyedMonster
Ich habe es der Frage hinzugefügt, aber es war bereits in der Ausgabe von text.txt.
Chris
1
@ JohnSaunders - Es ist kein Duplikat dieser Frage. In dieser Frage verwendete die Person, die die Frage stellte, LoadXml, um eine XML-Datei zu analysieren. Ich analysiere einen String, der die richtige Verwendung von ist LoadXml.
Chris
1
@marc_s: Kann ein stringUTF-8 jemals wirklich sein? Was ist, wenn die Verarbeitungsanweisung (erste Zeile) vor dem Laden entfernt wird?
John Saunders
2
Wenn ich Ihren Code nehme und kompiliere und ausführe, erhalte ich keine Fehler. Aber das liegt vielleicht daran, dass ich myString fest codiert fülle. Wie wird Ihr myString eingestellt? Wenn es aus einer anderen Datei oder einem anderen Stream stammt, ist möglicherweise etwas nerviges als Byte-Order-Mark am oberen Rand der Datei. Es wird normalerweise nicht von Editoren angezeigt (es sei denn, sie haben einen Hex-Modus).
Richard

Antworten:

118

Das versteckte Zeichen ist wahrscheinlich Stückliste. Die Erklärung des Problems und die Lösung finden Sie hier , James Schubert zu verdanken, basierend auf einer Antwort von James Brankin, die hier zu finden ist .

Die vorherige Antwort entfernt zwar das versteckte Zeichen, aber auch die gesamte erste Zeile. Die genauere Version wäre:

string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xml.StartsWith(_byteOrderMarkUtf8))
{
    xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
}

Dieses Problem trat auf, als ich eine XSLT-Datei aus dem Azure-Blob abrief und in ein XslCompiledTransform-Objekt lud. Auf meinem Computer sah die Datei gut aus, aber nachdem ich sie als Blob hochgeladen und zurückgerufen hatte, wurde das Stücklistenzeichen hinzugefügt.

Amit Merin
quelle
3
Ich bin mir nicht sicher und ich denke, ich muss weiter suchen, aber wenn ich das mache _byteOrderMarkUtf8 = "". also fängt es es nicht auf. Ideen?
user1040975
1
versuchte es, half nicht. xml kommt von db für diese Angelegenheit
John Demetriou
1
Encoding.UTF8.GetString (Encoding.UTF8.GetPreamble ()) ergibt eine leere Zeichenfolge
Mister Cook
6
Hatte die gleichen Probleme wie die oben genannten Kommentatoren. Verwenden xmlStartsWith(byteOrderMarkUtf8, StringComparison.Ordinal)hat den Trick für mich getan. Dank
Polshgiant
2
Dies löste das Problem für mich, vielen Dank, ich habe jetzt schon eine Weile meinen Kopf darauf geschlagen.
Mknopf
62

Verwenden Sie Load()stattdessen die Methode, um das Problem zu lösen. Mehr sehen

Ringo
quelle
15
Ich verwende XDocument.Load () und habe das Problem.
B. Clay Shannon
1
Es scheint, dass XmlDocument.Load () sich um die Dateicodierung kümmert, wenn sie folglich im Header angegeben wird. Wenn nicht, muss man sich möglicherweise mit StreamReader und XmlDocument.LoadXml und anderen Tools befassen.
CLS
14

Das Problem hier war, myStringdass diese Kopfzeile hatte. Entweder befand sich am Anfang der ersten Zeile ein verstecktes Zeichen, oder die Zeile selbst verursachte den Fehler. Ich habe die erste Zeile so abgeschnitten:

xml.LoadXml(myString.Substring(myString.IndexOf(Environment.NewLine)));

Dies löste mein Problem.

Chris
quelle
4
Einmal bekam ich diesen Fehler und es stellte sich heraus, dass ein '?' am Anfang. Ich habe es gerade durch ein Leerzeichen ersetzt und es zum Laufen gebracht ... Das kann auch passieren, wenn die Datei, die Sie lesen, eine andere Codierung hat als erwartet
Ricardo Appleton,
Ich habe dies versucht, aber in .NETPrehistoric (1.1) habe ich versucht, "\ r \ n" anstelle der damals nicht verfügbaren Environment.NewLine zu verwenden. Ich bekam: "Das angegebene Argument lag außerhalb des Bereichs gültiger Werte."
B. Clay Shannon
@ Chris: Ich habe deine Lösung ausprobiert. Ich komme unter die Ausnahme. System.ArgumentOutOfRangeException: StartIndex darf nicht kleiner als Null sein. Parameter
Shesha
10

Ich denke, dass das Problem in der Codierung liegt. Aus diesem Grund kann das Problem durch Entfernen der ersten Zeile (mit Codierungsbyte) behoben werden.

Meine Lösung für Daten auf Stammebene ist ungültig. Zeile 1, Position 1. in XDocument.Parse(xmlString)wurde durch ersetztXDocument.Load( new MemoryStream( xmlContentInBytes ) );

Ich habe festgestellt, dass meine XML-Zeichenfolge in Ordnung aussah:

<?xml version="1.0" encoding="utf-8"?>

aber in verschiedenen Texteditor-Codierungen sah es so aus:

?<?xml version="1.0" encoding="utf-8"?>

Am Ende brauchte ich nicht die XML-Zeichenfolge, sondern XML-Byte []. Wenn Sie die Zeichenfolge verwenden müssen, sollten Sie nach "unsichtbaren" Bytes in Ihrer Zeichenfolge suchen und mit Codierungen spielen, um den XML-Inhalt für das Parsen oder Laden anzupassen.

Hoffe es wird helfen

pawciu
quelle
3

Ich habe dieses Problem gelöst, indem ich das Byte-Array direkt bearbeitet habe. Sammeln Sie die UTF8-Präambel und entfernen Sie direkt den Header. Anschließend können Sie das Byte [] mit der GetString-Methode in einen String umwandeln (siehe unten). Das \ r und \ t habe ich ebenfalls vorsichtshalber entfernt.

XmlDocument configurationXML = new XmlDocument();
List<byte> byteArray = new List<byte>(webRequest.downloadHandler.data);

foreach(byte singleByte in Encoding.UTF8.GetPreamble())
{
     byteArray.RemoveAt(byteArray.IndexOf(singleByte));
}
string xml = System.Text.Encoding.UTF8.GetString(byteArray.ToArray());
       xml = xml.Replace("\\r", "");
       xml = xml.Replace("\\t", "");
Michael Planer
quelle
Es ist Arbeit für mich. Aber in der Schleife müssen wir byteArray.IndexOf (singleByte)! = -1 überprüfen oder nicht, bevor wir es entfernen.
ThanhLD
2

Speichern Sie Ihre Datei mit einer anderen Codierung:

Datei> Datei speichern unter ...> Als UTF-8 ohne Signatur speichern.

In VS 2017 finden Sie die Codierung als Dropdown-Liste neben der Schaltfläche Speichern.

MikeMajara
quelle
2

Zuerst hatte ich Probleme, dem "&" -Zeichen zu entkommen, dann wurden diakritische Zeichen und Sonderbuchstaben als Fragezeichen angezeigt und endeten mit dem erwähnten Problem OP.

Ich habe mir die Antworten angesehen und @ Ringos Vorschlag verwendet, um alternativ die Load () -Methode auszuprobieren. Dadurch wurde mir klar, dass ich mit meiner Antwort auf andere Weise umgehen kann, nicht nur als Zeichenfolge.

Die Verwendung von System.IO.Stream anstelle von String löste alle Probleme für mich.

var response = await this.httpClient.GetAsync(url);
var responseStream = await response.Content.ReadAsStreamAsync();
var xmlDocument = new XmlDocument();
xmlDocument.Load(responseStream);

Das Coole an Load () ist, dass diese Methode das Zeichenfolgenformat des Eingabe-XML (z. B. UTF-8, ANSI usw.) automatisch erkennt. Mehr sehen

Tibbiustin
quelle
1

Wenn sich Ihre XML in einer Zeichenfolge befindet, verwenden Sie Folgendes, um alle Bytereihenfolgen zu entfernen:

        xml = new Regex("\\<\\?xml.*\\?>").Replace(xml, "");
Herr Koch
quelle
Wirklich mein Leben gerettet. Ich habe alle Vorschläge ausprobiert, aber Ihre Lösung hat mein Problem gelöst. Vielen Dank!
Tornike Gomareli
0

Ich habe eine der Lösungen gefunden. Für Ihren Code könnte dies wie folgt sein:

XmlDocument xml = new XmlDocument();
try
{
    // assuming the location of the file is in the current directory 
    // assuming the file name be loadData.xml
    string myString = "./loadData.xml";
    xml.Load(myString);
}
catch (Exception ex)
{
    System.IO.File.WriteAllText(@"C:\text.txt", myString + "\r\n\r\n" + ex.Message);
    throw ex;
}
Shubhasish Bhunia
quelle
Es ist eine Lösung, aber eine schlechte. Dies ist ein Codierungsproblem. Durch Schreiben und Lesen einer Datei haben Sie die Codierung und Decodierung tatsächlich durchgeführt, ohne sich dessen bewusst zu sein, da die aufgerufene Überladung der Load-Methode den Standardwert für den Codierungsparameter (System.Text.Encoding-Codierung) hat
hardyVeles
Vielen Dank, Sir, dass Sie darauf hingewiesen haben. Könnten Sie mich bitte korrigieren?
Shubhasish Bhunia
Sie sollten den String mit Methoden der Encoding-Klasse dekodieren und kodieren. Es ist nicht erforderlich (und sinnvoll), überhaupt Dateimethoden oder Dateisysteme zu verwenden. Bitte überprüfen Sie: docs.microsoft.com/en-us/dotnet/api/…
hardyVeles
0

wenn wir XDocument.Parse (@ "") verwenden. Use @ it behebt das Problem.

Raj
quelle
0

Hauptverursacher dieses Fehlers ist die Logik, die die Codierung beim Konvertieren Streamoder byte[]Array in .NET bestimmtstring .

Wenn Sie den StreamReaderParameter mit dem zweiten Konstruktor detectEncodingFromByteOrderMarksauf true setzen, wird die richtige Codierung ermittelt und erstellt, stringwodurch die XmlDocument.LoadXmlMethode nicht unterbrochen wird.

public string GetXmlString(string url)
{
    using var stream = GetResponseStream(url);
    using var reader = new StreamReader(stream, true);
    return reader.ReadToEnd(); // no exception on `LoadXml`
}

Ein häufiger Fehler wäre, einfach blind die UTF8Codierung auf dem streamoder zu verwenden byte[]. Der folgende Code erzeugt einen Wert string, der gültig aussieht, wenn er im Visual Studio-Debugger überprüft oder irgendwo kopiert wird. Bei Verwendung mit Loadoder LoadXmlwenn die Datei anders codiert ist als UTF8 ohne Stückliste , wird jedoch die Ausnahme erzeugt .

public string GetXmlString(string url)
{
    byte[] bytes = GetResponseByteArray(url);
    return System.Text.Encoding.UTF8.GetString(bytes); // potentially exception on `LoadXml`
}
Nenad
quelle