XML 中的無效字符
1. 概述
XML(可擴展標記語言)是跨各種平台和應用程式儲存和傳輸資料最廣泛使用的格式之一。然而,儘管 XML 很健壯,但它也不能避免問題,其中一項挑戰就是處理 XML 文件中的無效字元。
在本文中,我們將了解不同的無效字元以及如何在 XML 處理中處理它們。
2. XML 中的有效字符
XML 規範定義了元素內容和屬性值中允許使用的字元。根據 XML 1.0 規範,可接受的字元如下所示。 XML 將這些範圍之外的任何字元視為無效字元:
描述 | 範圍 | 例子 |
---|---|---|
製表符(水平製表符) | 9(製表符) | \t |
換行符號(換行) | 10(低頻) | \n |
回車符(返回行首) | 13(CR) | \r |
基本多語言平面(BMP) 中的字符,不包括代理塊 | 32 至 55295 | A、b、&、1、α(希臘字母 alpha) |
補充私人使用區域 A (SMP) 中的字符,不包括代理塊 | 57344 至 65533 | 😊(笑臉),🎉(派對爆款) |
補充平面中超出 BMP 的字符 | 65536 轉 1114111 | 🌍(有經絡的地球儀),🚀(火箭) |
注意:在 Unicode 中,我們使用代理區塊作為 UTF-16 編碼中的特定代碼點範圍來表示基本多語言平面之外的字元。
3. XML 1.1 和處理無效字符
XML 1.1 作為 XML 1.0 的更新版本引入,提供了額外的靈活性並支援更廣泛的字符,包括整個 Unicode 字元集中的字元。它允許 1-31 範圍內的字符(TAB、LF 和 CR 除外)和某些控製字符,例如 NEL(下一行,Unicode 0 x0085
)。
4. XML 中的無效字符
XML 中的無效字元通常分為兩類:
4.1.保留字元
XML 在其語法中保留某些用於特定目的的字符,例如<
、 >,
&,
“
和'
。當這些字元出現在沒有正確編碼的 XML 元素上下文中時,它們可能會中斷解析過程並使 XML 文件無效。讓我們看一個程式碼範例,其中我們提供了無效字元:
@Test
void givenXml_whenReservedCharacters_thenThrowException() {
String invalidXmlString = "<?xml version=\"1.1\" encoding=\"UTF-8\"?><root><name>John & Doe</name></root>";
assertThrowsExactly(SAXParseException.class, () -> parseXmlString(invalidXmlString));
}
我們應該使用預先定義的字元實體正確轉義保留字元。例如:
-
<
應<
為 < -
>
應>
為 > -
&
應編碼為&
-
“
應該編碼為"
-
'
應'
為 '
我們可以透過執行以下測試來測試它:
@Test
void givenXml_whenReservedCharactersEscaped_thenSuccess() {
String validXmlString = "<?xml version=\"1.1\" encoding=\"UTF-8\"?><root><name>John & Doe</name></root>";
assertDoesNotThrow(() -> {
Document document = parseXmlString(validXmlString);
assertNotNull(document);
assertEquals("John & Doe", document.getElementsByTagName("name").item(0).getTextContent());
});
}
處理 XML 中保留字元的另一種方法是利用CDATA 部分。它用作封裝可能包含否則解釋為標記的字元的文字區塊的方法:
@Test
void givenXml_whenUsingCdataForReservedCharacters_thenSuccess() {
String validXmlString = "<?xml version=\"1.1\" encoding=\"UTF-8\"?><root><name><![CDATA[John & Doe]]></name></root>";
assertDoesNotThrow(() -> {
Document document = parseXmlString(validXmlString);
assertNotNull(document);
assertEquals("John & Doe", document.getElementsByTagName("name").item(0).getTextContent());
});
}
4.2.統一碼字符
XML 文件使用 Unicode 進行編碼,它支援來自不同語言和腳本的大量字元。雖然 Unicode 提供了廣泛的覆蓋範圍,但它也包含可能與 XML 編碼標準不相容的字符,從而導致解析錯誤。
讓我們檢查以下測試場景,其中我們在 XML 中合併了記錄分隔符號。 Unicode 將記錄分隔符號表示為\u001E
:
@Test
void givenXml_whenUnicodeCharacters_thenThrowException() {
String invalidXmlString = "<?xml version=\"1.1\" encoding=\"UTF-8\"?><root><name>John \u001E Doe</name></root>";
assertThrowsExactly(SAXParseException.class, () -> parseXmlString(invalidXmlString));
}
該字元的 ASCII 值為 30,超出了可接受的範圍。因此,解析它的測試將會失敗。為了正確處理非 ASCII 字符,我們應該使用 UTF-8 或 UTF-16 等 Unicode 方案對其進行編碼。
這確保了不同平台之間的相容性並避免資料損壞問題。現在讓我們使用正確的編碼執行以下測試:
@Test
void givenXml_whenUnicodeCharactersEscaped_thenSuccess() {
String validXmlString = "<?xml version=\"1.1\" encoding=\"UTF-8\"?><root><name>John  Doe</name></root>";
assertDoesNotThrow(() -> {
Document document = parseXmlString(validXmlString);
assertNotNull(document);
assertEquals("John \u001E Doe", document.getElementsByTagName("name").item(0).getTextContent());
});
}
5. 結論
在本文中,我們研究了 XML 中的不同無效字元以及如何有效地處理它們。透過了解無效字元的原因並採用適當的處理策略,開發人員可以確保其 XML 處理管道的穩健性和可靠性。
與往常一樣,完整的源代碼可以在 GitHub 上取得。