[英]How to beautify incomplete XML documents
我正在尋找一種美化不完整 XML 文檔的方法。 在最好的情況下,它甚至應該處理大尺寸(例如 10 MB 或 100 MB)。
不完整意味着文檔在隨機位置被截斷。 在此位置之前,XML 具有有效的語法。 美化意味着在標簽之間添加換行符和前導空格。
在我的情況下,需要分析中止的流。 沒有換行符和縮進,對於人類來說真的很難閱讀。 我知道有一些編輯器可以美化不完整的文檔,但我想將美化器集成到我自己的分析工具中。
不幸的是,我沒有找到該案例的討論或解決方案。
Kirill Osenkov 的 nuget 包GuiLabs.Language.Xml
(存儲庫XmlParser )似乎是自己的美化器實現的有用候選者,因為它被設計為容錯。 不幸的是,了解如何使用此解析器的文檔太少。
示例 xml:
<?xml encoding="UTF-8"?><X><B><C>aa</C><B/><A.B><X>bb</X></A.B><A p="pp"/><nn:A>cc</nn:A><D><E>eee</
預期結果為字符串:
<?xml encoding="UTF-8"?>
<X>
<B>
<C>aa</C>
<B/>
<A.B>
<X>bb</X>
</A.B>
<A p="pp"/>
<nn:A>cc</nn:A>
<D>
<E>eee</
必須是 C# 嗎?
在 Java 中,您應該能夠通過使用身份轉換器將 SAXSource 連接到 StreamResult 來將 SAX 解析器的輸出通過管道傳輸到縮進序列化程序中,然后確保在 SAX 解析器中止時捕獲異常並關閉輸出流整齊。
我認為您可能可以在 C# 中做同樣的事情,但不是那么方便:耦合從 XmlReader 讀取的事件並將相應的事件發送到 XmlWriter 會更加乏味,因為您必須為每種單獨的事件編寫代碼。
如果您需要 C# 解決方案並且准備安裝 Saxon 企業版,您可以編寫一個簡單的流轉換:
<transform version="3.0" xmlns="http://www.w3.org/1999/XSL/Transform">
<output method="xml" indent="yes"/>
<mode streamable="yes" on-no-match="shallow-copy"/>
</transform>
使用 XsltTransformer 作為目標從 Saxon API 調用它,並再次捕獲異常並刷新/關閉 Serializer 正在寫入的輸出流。
在 Java 上使用 Saxon 會有點過分,因為身份轉換器“開箱即用”。
AngleSharp.Xml 的忽略“XML”解析器的錯誤可用於解析您的示例,盡管會添加缺少的標簽,但您可以獲得構建文檔的 XML 字符串表示,並借助傳統的 XmlTextReader 和 XmlTextWriter要忽略命名空間,您至少可以縮進標記:
var xml = @"<?xml encoding=""UTF-8""?><X><B><C>aa</C><B/><A.B><X>bb</X></A.B><A p=""pp""/><nn:A>cc</nn:A><D><E>eee</";
var xmlParser = new XmlParser(new XmlParserOptions() { IsSuppressingErrors = true });
var doc = xmlParser.ParseDocument(xml);
Console.WriteLine(doc.ToMarkup());
using (StringReader sr = new StringReader(doc.ToXml()))
{
using (XmlTextReader xr = new XmlTextReader(sr))
{
xr.Namespaces = false;
using (XmlTextWriter xw = new XmlTextWriter(Console.Out))
{
xw.Namespaces = false;
xw.Formatting = Formatting.Indented;
xw.WriteNode(xr, false);
}
}
}
}
例如得到
<X>
<B>
<C>aa</C>
<B />
<A.B>
<X>bb</X>
</A.B>
<A p="pp" />
<nn:A>cc</nn:A>
<D>
<E>eee</E>
</D>
</B>
</X>
正如您的文字所說的“直到這個位置,XML 具有有效的語法”並且您的評論表明您的示例中的錯誤只是由於草率我認為也可以使用XmlWriter
WriteNode
並將XmlWriterSettings.Indent
設置為 true on標准XmlReader
,只要您捕獲XmlReader
拋出的異常:
var xml = @"<?xml version=""1.0""?><root><section><p>Paragraph 1.</p><p>Paragraph 2.";
try
{
using (StringReader sr = new StringReader(xml))
{
using (XmlReader xr = XmlReader.Create(sr))
{
using (XmlWriter xw = XmlWriter.Create(Console.Out, new XmlWriterSettings() { Indent = true }))
{
xw.WriteNode(xr, false);
}
}
}
}
catch (XmlException e)
{
Console.WriteLine();
Console.WriteLine("Malformed input XML: {0}", e.Message);
}
給
<?xml version="1.0"?>
<root>
<section>
<p>Paragraph 1.</p>
<p>Paragraph 2.</p>
</section>
</root>
Malformed input XML: Unexpected end of file has occurred. The following elements are not closed: p, section, root. Line 1, position 71.
所以不需要用WriteNode
來處理每一個可能的Readxxx
和節點類型,並通過你自己的代碼在XmlWriter上調用相應的Writexxx
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.