用C++或Qt格式化XML文件

8

我有一个XML文件,其中输出没有被格式化。这意味着所有的输出都在一行中,但我想要逐个标签地分开它。

例如 -

<?xml version="1.0" encoding="UTF-8" standalone="no" ?><Analyser>   <JointDetails>              <Details><StdThickness> T </StdThickness><Thickness_num> 0.032 </Thickness_num></Details>   </JointDetails></Analyser>

但我想要这样做:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Analyser>  
 <JointDetails>
   <Details>
<StdThickness> T </StdThickness>
<Thickness_num> 0.032 </Thickness_num>
</Details> 
  </JointDetails>
</Analyser>

请不要建议在编写XML文件时完成此操作,因为该XML文件已经存在,但现在我必须按照上述格式进行格式化。


1
使用TinyXML读取XML,使用默认的TiXMLPrinter进行输出,该打印机默认为漂亮的打印。 - Jerry Coffin
5个回答

10
使用 QXmlStreamReaderQXmlStreamWriter 应该可以满足您的需求。QXmlStreamWriter::setAutoFormatting(true) 可以在不同行上格式化 XML 并使用正确的缩进。使用 QXmlStreamReader::isWhitespace(),您可以过滤标记之间多余的空格。
QString xmlIn = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>"
                "<Analyser><JointDetails>              <Details><StdThickness>"
                " T </StdThickness><Thickness_num> 0.032 </Thickness_num>"
                "</Details>   </JointDetails></Analyser>";
QString xmlOut;

QXmlStreamReader reader(xmlIn);
QXmlStreamWriter writer(&xmlOut);
writer.setAutoFormatting(true);

while (!reader.atEnd()) {
    reader.readNext();
    if (!reader.isWhitespace()) {
        writer.writeCurrentToken(reader);
    }
}

qDebug() << xmlOut;

感谢您的回复。但是在第二次迭代期间出现了错误。 - Viku
你所说的"breaking"是什么意思?是指程序崩溃了吗?还是输出的结果不符合预期?这个测试程序应该可以打印出你想要的结果:https://gist.github.com/4343585 - stijnvn
哎呀,程序崩溃了。 - Viku
@viku:你能提供更多有关崩溃的细节吗(回溯、错误消息等)? - stijnvn

3
void format(void)
{
    QDomDocument input;

    QFile inFile("D:/input.xml");
    QFile outFile("D:/output.xml");

    inFile.open(inFile.Text | inFile.ReadOnly);
    outFile.open(outFile.Text | outFile.WriteOnly);

    input.setContent(&inFile);

    QDomDocument output(input);
    QTextStream stream(&outFile);
    output.save(stream, 2);
}

3

如果您正在使用Qt,可以使用QXmlStreamReader读取它,并使用QXmlStreamWriter编写它,或将其解析为QDomDocument并将其转换回QString。 QXmlStreamWriter和QDomDocument都支持格式化。


3

如果您想要一个简单而稳健的解决方案,而不是依赖于QT,那么您可以使用libxml2。(如果您已经使用QT了,只需按照Frank Osterfeld所说的去用即可。)

xmlDoc* xdoc = xmlReadFile(BAD_CAST"myfile.xml", NULL, NULL, 0);
xmlSaveFormatFile(BAD_CAST"myfilef.xml", xdoc, 1);
xmlFreeDoc(xdoc);

我可以向您介绍我的C++ libxml2包装器吗?

编辑: 如果您恰好在内存中拥有XML字符串,您也可以使用xmlReadDoc... 但这并不止于此。


0

利用C++,您可以在每个><实例之间添加一个单字符以进行输出:通过将><更改为>\n<(这会添加非打印字符以进行换行),每个标记都将打印到新行上。虽然有API的方法可以做到这一点,但如上所述,对于控制台输出或使XML在文本编辑器等工具中每个标记都流到新行上的简单方法,\n应该可以很好地工作。

如果您需要更优雅的输出,可以使用\n(换行)和\t(制表符)编写自己的方法来布置输出,或者利用API,如果您需要更精细的表示。


实际上,我想将上面的输出存储到文件中。但我认为 \n 只适用于控制台。您能否建议一些方法来将其存储到文件中? - Viku
你是如何将内容流式保存到文件中的?例如,如果你将XML字符串保存为文本文件,那么\n也会起作用,所以你可以放心这样做。你可以使用额外的API来美化你的XML输出,不过自己编写系统的优势在于你可以了解所有工作原理,并且可以根据自己的需要编写一个小而高效的系统。这真的因人而异,但如果你需要更详细的答案,我会尽力提供,只需要一些关于你实际上是如何保存内容到文件中的额外信息就可以了。 :) - GMasucci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接