xml.LoadData - Dữ liệu ở cấp cơ sở không hợp lệ. Dòng 1, vị trí 1


78

Tôi đang cố gắng phân tích cú pháp một số XML bên trong trình cài đặt WiX. XML sẽ là một đối tượng của tất cả các lỗi của tôi được trả về từ một máy chủ web. Tôi gặp lỗi trong tiêu đề câu hỏi với mã này:

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

myStringđây có phải là (như được thấy trong đầu ra của text.txt)

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

text.txt xuất hiện như thế này:

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

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

Tôi cần XML này để phân tích cú pháp để có thể xem liệu tôi có gặp lỗi nào không.

Biên tập

Câu hỏi này không phải là một bản sao như đã đánh dấu. Trong câu hỏi đó, người đặt câu hỏi đang sử dụng LoadXmlđể phân tích cú pháp một tệp XML. Tôi đang phân tích cú pháp một chuỗi, đây là cách sử dụng chính xác củaLoadXml


Sẽ thực sự cần phải xem xml để giúp đỡ
RedEyedMonster

Tôi đã thêm nó vào câu hỏi, nhưng nó đã có trong đầu ra của text.txt.
Chris

1
@JohnSaunders - Nó không phải là bản sao của câu hỏi đó. Trong câu hỏi đó, người đặt câu hỏi đang sử dụng LoadXml để phân tích cú pháp tệp XML. Tôi đang phân tích cú pháp một chuỗi, đó là cách sử dụng chính xác LoadXml.
Chris

1
@marc_s: có stringbao giờ thực sự là UTF-8 không? Điều gì sẽ xảy ra nếu lệnh xử lý (dòng đầu tiên) bị xóa trước khi tải?
John Saunders

2
Nếu tôi lấy mã của bạn và biên dịch và chạy nó, tôi không gặp lỗi. Nhưng đó có thể là do tôi điền vào mã cứng String của mình. Làm thế nào để chuỗi myString của bạn được thiết lập? Nếu nó đến từ một tệp hoặc luồng khác, có thể có điều gì đó gây phiền nhiễu như Dấu Byte-Thứ tự-Đánh dấu ở đầu tệp. Nó thường không được hiển thị bởi các biên tập viên (trừ khi họ có chế độ Hex).
Richard

Câu trả lời:


120

Nhân vật ẩn có lẽ là BOM. Lời giải thích cho vấn đề và giải pháp có thể được tìm thấy ở đây , ghi công cho James Schubert, dựa trên câu trả lời của James Brankin được tìm thấy ở đây .

Mặc dù câu trả lời trước không xóa ký tự bị ẩn, nó cũng xóa toàn bộ dòng đầu tiên. Phiên bản chính xác hơn sẽ là:

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

Tôi đã gặp sự cố này khi tìm nạp tệp XSLT từ Azure blob và tải nó vào đối tượng XslCompiledTransform. Trên máy của tôi, tệp trông vẫn ổn, nhưng sau khi tải nó lên dưới dạng đốm màu và tìm nạp lại, ký tự BOM đã được thêm vào.


3
Tôi không chắc và tôi đoán tôi sẽ phải tiếp tục tìm kiếm, nhưng khi tôi làm điều này _byteOrderMarkUtf8 = "". vì vậy nó không bắt được nó. Ý tưởng?
user1040975

1
đã thử nó, đã không giúp đỡ. xml đến từ db cho rằng vấn đề
John Demetriou

1
Encoding.UTF8.GetString (Encoding.UTF8.GetPreamble ()) đánh giá thành một chuỗi rỗng
Mister Cook

6
Có cùng vấn đề như những người bình luận ở trên. Sử dụng xmlStartsWith(byteOrderMarkUtf8, StringComparison.Ordinal)đã làm các mẹo cho tôi.
Ghi có

2
Điều này đã giải quyết vấn đề cho tôi, cảm ơn bạn RẤT nhiều, tôi đã đập đầu vào điều này một lúc rồi.
mknopf

63

Sử dụng Load()phương pháp thay thế, nó sẽ giải quyết vấn đề. Xem thêm


16
Tôi đang sử dụng XDocument.Load () và tôi gặp sự cố.
B. Clay Shannon

1
Có vẻ như XmlDocument.Load () chăm sóc Mã hóa tệp khi do đó nó được chỉ định trong tiêu đề. Khi không, người ta có thể phải xử lý StreamReader và XmlDocument.LoadXml và các công cụ khác.
CLS

Đây là bản sửa lỗi của tôi vào năm 2020
MX313

15

Vấn đề ở đây là myStringcó dòng tiêu đề đó. Có một số ký tự ẩn ở đầu dòng đầu tiên hoặc chính dòng đó đang gây ra lỗi. Tôi cắt bỏ dòng đầu tiên như vậy:

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

Điều này đã giải quyết vấn đề của tôi.


4
Một khi tôi gặp lỗi này và nó chuyển thành dấu '?' Tại thời điểm bắt đầu. Tôi chỉ thay thế nó với một khoảng trống và đã cho nó chạy ... Đó cũng có thể xảy ra nếu các tập tin bạn đang đọc là trong một mã hóa khác với những gì bạn đang mong đợi
Ricardo Appleton

Tôi đã thử điều này, nhưng trong .NETPrehistoric (1.1), tôi đã cố gắng sử dụng "\ r \ n" thay cho Môi trường mới không khả dụng khi đó. Tôi nhận được, "Đối số được chỉ định nằm ngoài phạm vi giá trị hợp lệ."
B. Clay Shannon

@Chris: Tôi đã thử giải pháp của bạn. Tôi nhận được dưới đây ngoại lệ. System.ArgumentOutOfRangeException: StartIndex không được nhỏ hơn 0. Tham số
Shesha

10

Tôi nghĩ rằng vấn đề là về mã hóa. Đó là lý do tại sao loại bỏ dòng đầu tiên (với byte mã hóa) có thể giải quyết được vấn đề.

Giải pháp của tôi cho Dữ liệu ở cấp cơ sở không hợp lệ. Dòng 1, vị trí 1. trong XDocument.Parse(xmlString)được thay thế bằngXDocument.Load( new MemoryStream( xmlContentInBytes ) );

Tôi nhận thấy rằng chuỗi xml của tôi trông ổn:

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

nhưng trong mã hóa trình soạn thảo văn bản khác, nó trông như thế này:

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

Cuối cùng, tôi không cần chuỗi xml mà là byte xml []. Nếu bạn cần sử dụng chuỗi, bạn nên tìm các byte "vô hình" trong chuỗi của mình và chơi với các mã hóa để điều chỉnh nội dung xml để phân tích cú pháp hoặc tải.

Hy vọng nó sẽ giúp ích


3

Tôi đã giải quyết vấn đề này bằng cách chỉnh sửa trực tiếp mảng byte. Thu thập phần mở đầu UTF8 và loại bỏ trực tiếp phần đầu. Sau đó, bạn có thể biến đổi byte [] thành chuỗi bằng phương thức GetString, xem bên dưới. \ R và \ t tôi cũng đã xóa, chỉ để đề phòng.

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

Nó làm việc cho tôi. Nhưng trong vòng lặp, chúng ta cần kiểm tra byteArray.IndexOf (singleByte)! = -1 hay không trước khi loại bỏ nó.
ThanhLD 19/08/19

2

Lưu tệp của bạn với mã hóa khác nhau:

Tệp> Lưu tệp dưới dạng ...> Lưu dưới dạng UTF-8 mà không cần chữ ký.

Trong VS 2017, bạn tìm thấy mã hóa dưới dạng trình đơn thả xuống bên cạnh nút Lưu.


2

Lúc đầu, tôi gặp sự cố khi thoát ký tự "&", sau đó dấu phụ và các chữ cái đặc biệt được hiển thị dưới dạng dấu hỏi và kết thúc với vấn đề OP đã đề cập.

Tôi đã xem các câu trả lời và tôi đã sử dụng đề xuất của @ Ringo để thử phương thức Load () như một phương thức thay thế. Điều đó khiến tôi nhận ra rằng tôi có thể giải quyết phản hồi của mình theo những cách khác chứ không chỉ là một chuỗi.

sử dụng System.IO.Stream thay vì chuỗi đã giải quyết tất cả các vấn đề cho tôi.

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

Điều thú vị về Load () là phương thức này tự động phát hiện định dạng chuỗi của XML đầu vào (ví dụ: UTF-8, ANSI, v.v.). Xem thêm


1

Nếu xml của bạn nằm trong một chuỗi, hãy sử dụng cách sau để xóa bất kỳ dấu thứ tự byte nào:

        xml = new Regex("\\<\\?xml.*\\?>").Replace(xml, "");

Thực sự đã cứu mạng tôi. Tôi đã thử tất cả các đề xuất nhưng giải pháp của bạn đã giải quyết được vấn đề của tôi. Cảm ơn rât nhiều!
Tornike Gomareli

0

Tôi đã tìm ra một trong những giải pháp. Đối với mã của bạn, điều này có thể như sau:

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

Đó là một giải pháp nhưng không tốt. Đây là vấn đề Encoding, bằng cách viết và đọc file, bạn thực sự thực hiện mã hóa và giải mã mà không biết, vì tình trạng quá tải của Viện dẫn các phương thức Load có giá trị mặc định cho Encoding tham số (System.Text.Encoding mã hóa)
hardyVeles

cảm ơn bạn ạ đã chỉ ra nó, bạn có thể xin vui lòng sửa chữa cho tôi?
Shubhasish Bhunia

Bạn nên giải mã và mã hóa Chuỗi, sử dụng các phương thức của lớp Mã hóa, không cần (và ý nghĩa) sử dụng các phương thức Tệp hoặc hệ thống tệp cả. Vui lòng kiểm tra: docs.microsoft.com/en-us/dotnet/api/…
hardyVeles

0

nếu chúng tôi đang sử dụng XDocument.Parse (@ ""). Sử dụng @ nó giải quyết vấn đề.


0

Thủ phạm chính cho lỗi này là logic xác định mã hóa khi chuyển đổi Streamhoặc byte[]mảng sang .NET string.

Sử dụng StreamReaderđược tạo với tham số hàm tạo thứ 2 detectEncodingFromByteOrderMarksđược đặt thành true, sẽ xác định mã hóa thích hợp và tạo phương thức stringkhông phá vỡ XmlDocument.LoadXml.

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

Sai lầm phổ biến sẽ là chỉ sử dụng UTF8mã hóa một cách mù quáng trên streamhoặc byte[]. Đoạn mã dưới đây sẽ tạo ra stringcó vẻ hợp lệ khi được kiểm tra trong trình gỡ lỗi Visual Studio hoặc sao chép ở đâu đó, nhưng nó sẽ tạo ra ngoại lệ khi được sử dụng với Loadhoặc LoadXmlnếu tệp được mã hóa khác UTF8 mà không có BOM.

public string GetXmlString(string url)
{
    byte[] bytes = GetResponseByteArray(url);
    return System.Text.Encoding.UTF8.GetString(bytes); // potentially exception on `LoadXml`
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.