3

我需要编写一个工具来处理以下格式不正确的 XML 片段,因为它在流中间包含 XML 声明。

该公司已经使用了很长时间的此类文件,因此无法更改格式。

没有可用于解析的源代码,新工具的首选平台是 .NET 4 或更新版本,最好使用 C#。

这是片段的样子:

<Header>
  <Version>1</Version>
</Header>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>
<Entry><?xml version="1.0"?><Detail>...snip...</Detail></Entry>

使用XmlReader并将XmlReaderSettings.ConformanceLevel设置为ConformanceLevel.Fragment,我可以<Header>很好地阅读完整的元素。即使<Entry>元素开始也可以,但是在读取<Detail>信息时XmlReader它会抛出XmlException,因为它在<?xml...?>XML 声明中读取它并不期望在那个地方。

除了繁重的字符串操作之外,我还有哪些选择可以跳过这些 XML 声明?

由于片段可以轻松超过 100 兆字节,我宁愿不要一次将所有内容加载到内存中。但这就是它所需要的,我对此持开放态度。

我得到的异常示例:

System.Xml.XmlException: Unexpected XML declaration.
The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it.
Line ##, position ##.
4

3 回答 3

2

我不认为内置类会有所帮助。您可能需要做一些准备并删除额外的标题。如果您的样本是准确的,您可以做一个string.Replace(badXml, "<?xml version=\"1.0\"?>, "")并继续前进。

于 2012-08-13T12:01:41.290 回答
1

如果您不确定声明是否始终保持不变,请替换<?xml<XmlDeclaration?>/>使用常规解析器;)

另外,您是否尝试过通过 XML tidy 样式程序传递文件?

您可能还可以使用 SGML 库来预处理数据并输出正确的 XML。

于 2012-08-13T12:19:12.883 回答
0

我将此添加为答案,因为它保留了语法突出显示。

    private void ProcessFile(string inputFileName, string outputFileName)
    {
        using (StreamReader reader = new StreamReader(inputFileName, new UTF8Encoding(false, true)))
        {
            using (StreamWriter writer = new StreamWriter(outputFileName, false, Encoding.UTF8))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    const string xmlDeclarationStart = "<?xml";
                    const string xmlDeclarationFinish = "?>";
                    if (line.Contains(xmlDeclarationStart))
                    {
                        string newLine = line.Substring(0, line.IndexOf(xmlDeclarationStart));
                        int endPosition = line.IndexOf(xmlDeclarationFinish, line.IndexOf(xmlDeclarationStart));
                        if (endPosition == -1)
                        {
                            throw new NotImplementedException(string.Format("Implementation assumption is wrong. {0} .. {1} spans multiple lines (or input file is severely misformed)", xmlDeclarationStart, xmlDeclarationFinish));
                        }
                        // the code completely strips the <?xml ... ?> part
                        // an alternative would be to make this a new XML element containing
                        // the information inside the <?xml ... ?> part as attributes
                        // just like Daren Thomas suggested
                        newLine += line.Substring(endPosition + 2);
                        line = newLine;
                    }
                    writer.WriteLine(line);
                }
            }
        }
    }
于 2013-02-13T09:10:24.260 回答