我正在编写一个派生自wxStyledTextCtrl的类,我想让它美化给定的XML而不添加除空格之外的任何内容。我找不到简单的工作方案。我只能使用wxStyledTextCtrl,wxXmlDocument和libxml2。
我的目标是在使用包含以下文本的wxString调用SetText之后
<!-- comment1 --> <!-- comment2 --> <node><emptynode/> <othernode>value</othernode></node>
控件应显示
<!-- comment1 -->
<!-- comment2 -->
<node>
<emptynode/>
<othernode>value</othernode>
</node>
使用libxml2我设法几乎实现了这一点,但它也打印了XML声明(例如<?xml version="1.0" encoding="UTF-8"?>
),我不想这样做。
inb4,我正在寻找简单而干净的解决方案 - 我不想手动删除第一行格式化的XML
使用给定的工具是否有任何简单的解决方案?我觉得我错过了什么。
答案 0 :(得分:0)
有简单的解决方案吗?不。但是如果你想写自己漂亮的打印功能,你基本上需要在xml文档树上进行深度优先迭代,然后随时打印。有一点轻微的复杂性,你还需要一些知道何时关闭标签的方法。
这是使用wxWidgets xml类完成此操作的一种方法的不完整示例。目前,它不处理属性,自闭元素(例如示例文本中的'')或任何其他特殊元素类型。一个完整漂亮的打印机需要添加这些东西。
#include <stack>
#include <set>
#include <wx/xml/xml.h>
#include <wx/sstream.h>
wxString PrettyPrint(const wxString& in)
{
wxStringInputStream string_stream(in);
wxXmlDocument doc(string_stream);
wxString pretty_print;
if (doc.IsOk())
{
std::stack<wxXmlNode*> nodes_in_progress;
std::set<wxXmlNode*> visited_nodes;
nodes_in_progress.push(doc.GetDocumentNode());
while (!nodes_in_progress.empty())
{
wxXmlNode* cur_node = nodes_in_progress.top();
nodes_in_progress.pop();
int depth = cur_node->GetDepth();
for (int i=1;i<depth;++i)
{
pretty_print << "\t";
}
if (visited_nodes.find(cur_node)!=visited_nodes.end())
{
pretty_print << "</" << cur_node->GetName() << ">\n";
}
else if ( !cur_node->GetNodeContent().IsEmpty() )
{
//If the node has content, just print it now
pretty_print << "<" << cur_node->GetName() << ">";
pretty_print << cur_node->GetNodeContent() ;
pretty_print << "</" << cur_node->GetName() << ">\n";
}
else if (cur_node==doc.GetDocumentNode())
{
std::stack<wxXmlNode *> nodes_to_add;
wxXmlNode *child = cur_node->GetChildren();
while (child)
{
nodes_to_add.push(child);
child = child->GetNext();
}
while (!nodes_to_add.empty())
{
nodes_in_progress.push(nodes_to_add.top());
nodes_to_add.pop();
}
}
else if (cur_node->GetType()==wxXML_COMMENT_NODE)
{
pretty_print << "<!-- " << cur_node->GetContent() << " -->\n";
}
//insert checks for other types of nodes with special
//printing requirements here
else
{
//otherwise, mark the node as visited and then put it back
visited_nodes.insert(cur_node);
nodes_in_progress.push(cur_node);
//If we push the children in order, they'll be popped
//in reverse order.
std::stack<wxXmlNode *> nodes_to_add;
wxXmlNode *child = cur_node->GetChildren();
while (child)
{
nodes_to_add.push(child);
child = child->GetNext();
}
while (!nodes_to_add.empty())
{
nodes_in_progress.push(nodes_to_add.top());
nodes_to_add.pop();
}
pretty_print <<"<" << cur_node->GetName() << ">\n";
}
}
}
return pretty_print;
}