我有一个文件,它有效地包含多个相同格式的XML文件,因此该文件本身不是有效的XML;例如:
<?xml version='1.0' encoding='UTF-8'?>
<Proposal xmlns="a namespace">
<ASubnode>Text</ASubNode>
<LotsOfOtherNodes />
</Proposal>
<?xml version='1.0' encoding='UTF-8'?>
<Proposal xmlns="a namespace">
<ASubnode>Text</ASubNode>
<LotsOfOtherNodes />
</Proposal>
....
我想一次一个地处理所有Proposal节点;例如:
foreach (var proposal in file)
do something
我无法使用XmlReader,因为它在到达中间XML声明节点时会抛出异常。我可能会将整个文件读入一个字符串,然后使用Split方法,但这些文件的大小是千兆字节,因此作为一个选项并不是特别有吸引力。看起来我可以一次读取一行文件,通过正则表达式搜索相应的节点,但文件不是如上所述的行格式,每行一个节点,而是包含很长的多个节点行,以及节点文本中的随机换行符。
有没有一种方法可以实现这个目的而无需手工制作文本解析器?
答案 0 :(得分:2)
您有两种选择:
告诉XmlReader不要那么挑剔。将XmlReaderSettings.ConformanceLevel设置为ConformanceLevel.Fragment。这将使解析器忽略没有根节点的事实。
var settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
using (var reader = XmlReader.Create(textReader, settings))
{
...
}
使用“root”元素包装XML文件,这样您的文档将只有一个根节点
<?xml version='1.0' encoding='UTF-8'?> <root> <Proposal xmlns="a namespace"> <ASubnode>Text</ASubNode> <LotsOfOtherNodes /> </Proposal> <?xml version='1.0' encoding='UTF-8'?> <Proposal xmlns="a namespace"> <ASubnode>Text</ASubNode> <LotsOfOtherNodes /> </Proposal> .... </root>
答案 1 :(得分:0)
您可以逐行阅读文本而不实际解析xml,因为xml文档的标题是相同的:
mSplashThread = new Thread() {
@Override
public void run() {
try {
Thread.sleep(DURATION);
runOnUiThread(new Runnable() {
public void run() {
Intent intent = new Intent(Splash.this,
Main.class);
startActivity(intent);
finish();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
mSplashThread.start();
更新: 即使声明可以在一行之间开始,以下内容也会起作用:
IEnumerable<XDocument> GetDocuments(Stream bulkStream)
{
var reader = new StreamReader(bulkStream);
var sb = new StringBuilder();
var firstLine = reader.ReadLine();
string line = firstLine;
while(line != null)
{
sb.Clear();
sb.Append(firstLine);
while((line = reader.ReadLine()) != null && line != firstLine)
{
sb.Append(line);
}
yield return XDocument.Parse(sb.ToString());
}
}