XML 헤더가 포함 된 경우 C # XmlDocument.LoadXml (string)이 실패하는 이유는 무엇입니까?
다음 코드 샘플이 XmlException "루트 수준의 데이터가 잘못되었습니다. 줄 1, 위치 1"과 함께 실패하는 이유를 아는 사람이 있습니까?
var body = "<?xml version="1.0" encoding="utf-16"?><Report> ......"
XmlDocument bodyDoc = new XmlDocument();
bodyDoc.LoadXml(body);
배경
귀하의 질문에는 인코딩이 UTF-16으로 설정되어 있지만 문자열이 제대로 이스케이프되지 않았으므로 실제로 문자열을 질문에 정확하게 전치했는지 확실하지 않았습니다.
동일한 예외가 발생했습니다.
System.Xml.XmlException : 루트 수준의 데이터가 잘못되었습니다. 라인 1, 위치 1
그러나 내 코드는 다음과 같습니다.
string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<event>This is a Test</event>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
문제
문제는 문자열이 .NET에서 내부적으로 UTF-16으로 저장되지만 XML 문서 헤더에 지정된 인코딩이 다를 수 있다는 것입니다. 예 :
<?xml version="1.0" encoding="utf-8"?>
문자열의 각 유니 코드 문자는 유니 코드 코드 포인트 또는 유니 코드 문자의 서수 (숫자) 값이라고도하는 유니 코드 스칼라 값으로 정의됩니다. 각 코드 포인트는 UTF-16 인코딩을 사용하여 인코딩되며 인코딩의 각 요소의 숫자 값은 Char 개체로 표시됩니다.
즉, XML 헤더가있는 문자열에 XmlDocument.LoadXml ()을 전달할 때 인코딩이 UTF-16이라고 말해야합니다. 그렇지 않으면 실제 기본 인코딩이 헤더에보고 된 인코딩과 일치하지 않아 XmlException이 발생합니다.
해결책
이 문제에 대한 해결책은 Load 또는 LoadXml 메서드를 전달하는 모든 항목에 사용 된 인코딩이 XML 헤더에있는 것과 일치하는지 확인하는 것입니다. 위의 예에서 XML 헤더를 UTF-16 상태로 변경하거나 입력을 UTF-8로 인코딩하고 XmlDocument.Load 메서드 중 하나를 사용 합니다 .
아래는 UTF-8 인코딩 XML 문서를 정의하는 문자열을 사용하여 MemoryStream을 사용하여 XmlDocument를 빌드하는 방법을 보여주는 샘플 코드입니다 (물론 UTF-16 .NET 문자열로 저장 됨).
string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<event>This is a Test</event>";
// Encode the XML string in a UTF-8 byte array
byte[] encodedString = Encoding.UTF8.GetBytes(xml);
// Put the byte array into a stream and rewind it to the beginning
MemoryStream ms = new MemoryStream(encodedString);
ms.Flush();
ms.Position = 0;
// Build the XmlDocument from the MemorySteam of UTF-8 encoded bytes
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ms);
대신 사용 : 간단하고 효율적인 솔루션 LoadXml()
방법의 사용 Load()
방법
예를 들면 :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("sample.xml");
이 시도:
XmlDocument bodyDoc = new XmlDocument();
bodyDoc.XMLResolver = null;
bodyDoc.Load(body);
나는 그것을 알아. MSDN 설명서를 읽으면 문자열에서 읽을 때 LoadXml 대신 .Load를 사용한다고 말합니다. 이것이 100 % 작동한다는 것을 알았습니다. 이상하게도 StringReader를 사용하면 문제가 발생합니다. 주된 이유는 이것이 유니 코드로 인코딩 된 문자열이고 StringReader가 UTF-8 전용이기 때문에 문제를 일으킬 수 있기 때문이라고 생각합니다.
MemoryStream stream = new MemoryStream();
byte[] data = body.PayloadEncoding.GetBytes(body.Payload);
stream.Write(data, 0, data.Length);
stream.Seek(0, SeekOrigin.Begin);
XmlTextReader reader = new XmlTextReader(stream);
// MSDN reccomends we use Load instead of LoadXml when using in memory XML payloads
bodyDoc.Load(reader);
이것은 나를 위해 일했습니다.
var xdoc = new XmlDocument { XmlResolver = null };
xdoc.LoadXml(xmlFragment);
이것은 정말로 내 하루를 구했습니다.
Zach의 답변을 기반으로 확장 메서드를 작성했으며 인코딩을 매개 변수로 사용하도록 확장하여 UTF-8 이외의 다른 인코딩을 사용할 수 있도록하고 MemoryStream을 'using'문으로 래핑했습니다.
public static class XmlHelperExtentions
{
/// <summary>
/// Loads a string through .Load() instead of .LoadXml()
/// This prevents character encoding problems.
/// </summary>
/// <param name="xmlDocument"></param>
/// <param name="xmlString"></param>
public static void LoadString(this XmlDocument xmlDocument, string xmlString, Encoding encoding = null) {
if (encoding == null) {
encoding = Encoding.UTF8;
}
// Encode the XML string in a byte array
byte[] encodedString = encoding.GetBytes(xmlString);
// Put the byte array into a stream and rewind it to the beginning
using (var ms = new MemoryStream(encodedString)) {
ms.Flush();
ms.Position = 0;
// Build the XmlDocument from the MemorySteam of UTF-8 encoded bytes
xmlDocument.Load(ms);
}
}
}
I had the same problem when switching from absolute to relative path for my xml file. The following solves both loading and using relative source path issues. Using a XmlDataProvider, which is defined in xaml (should be possible in code too) :
<Window.Resources>
<XmlDataProvider
x:Name="myDP"
x:Key="MyData"
Source=""
XPath="/RootElement/Element"
IsAsynchronous="False"
IsInitialLoadEnabled="True"
debug:PresentationTraceSources.TraceLevel="High" /> </Window.Resources>
The data provider automatically loads the document once the source is set. Here's the code :
m_DataProvider = this.FindResource("MyData") as XmlDataProvider;
FileInfo file = new FileInfo("MyXmlFile.xml");
m_DataProvider.Document = new XmlDocument();
m_DataProvider.Source = new Uri(file.FullName);
Simple line:
bodyDoc.LoadXml(new MemoryStream(Encoding.Unicode.GetBytes(body)));
I had the same issue because the XML file I was uploading was encoded using UTF-8-BOM (UTF-8 byte-order mark).
Switched the encoding to UTF-8 in Notepad++ and was able to load the XML file in code.
'programing tip' 카테고리의 다른 글
Linq는 각 그룹별로, 그룹별로 정렬합니까? (0) | 2020.12.03 |
---|---|
Eclipse 프로그램에서 Java 키워드 어설 션을 활성화하는 방법은 무엇입니까? (0) | 2020.12.03 |
XML 속성을 통해 클래스 이름을 어떻게 바꿀 수 있습니까? (0) | 2020.12.03 |
Express js를 출력 파일에 로그인 하시겠습니까? (0) | 2020.12.03 |
nullable 형식으로 작동하지 않는 null 조건부 연산자? (0) | 2020.12.02 |