#输入的xml
<root>
<if condition="true">
<for count="2">
<item for="f1" if="f1i1">
Outer Item
<for count="2">
<if condition="true">
<subitem for="f2" if="f2i1">
Inner Item 1
<for count="3">
<if condition="true">
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</if>
<if condition="false">
<subsubitem for="f3" if="f3i2">Innermost Item</subsubitem>
</if>
</for>
</subitem>
</if>
<if condition="false">
<subitem for="f2" if="f2i2">
Inner Item 1
<for count="3">
<if condition="true">
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</if>
<if condition="false">
<subsubitem for="f3" if="f3i2">Innermost Item</subsubitem>
</if>
</for>
</subitem>
</if>
</for>
</item>
</for>
</if>
<if condition="true">
<for count="2">
<item for="f1" if="f1i2">
Outer Item
<for count="2">
<if condition="true">
<subitem for="f2" if="f2i1">
Inner Item 1
<for count="3">
<if condition="true">
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</if>
<if condition="false">
<subsubitem for="f3" if="f3i2">Innermost Item</subsubitem>
</if>
</for>
</subitem>
</if>
<if condition="false">
<subitem for="f2" if="f2i2">
Inner Item 1
<for count="3">
<if condition="true">
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</if>
<if condition="false">
<subsubitem for="f3" if="f3i2">Innermost Item</subsubitem>
</if>
</for>
</subitem>
</if>
</for>
</item>
</for>
</if>
</root>
#解析代码
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include "pugixml.hpp"
// 用于格式化节点的缩进
void add_indentation(pugi::xml_node node, int indent_level, std::ostringstream &oss) {
std::string indent(indent_level * 2, ' ');
if (node.type() == pugi::node_element) {
oss << "\n" << indent << "<" << node.name();
for (pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) {
oss << " " << attr.name() << "=\"" << attr.value() << "\"";
}
oss << ">";
bool has_children = false;
for (pugi::xml_node child = node.first_child(); child; child = child.next_sibling()) {
if (child.type() != pugi::node_pcdata) {
has_children = true;
break;
}
}
// 处理子节点
if (has_children) {
for (pugi::xml_node child = node.first_child(); child; child = child.next_sibling()) {
add_indentation(child, indent_level + 1, oss);
}
oss << "\n" << indent << "</" << node.name() << ">";
} else {
std::string text = node.child_value();
if (text.find_first_not_of(" \t\n\r") != std::string::npos) {
oss << text;
}
oss << "</" << node.name() << ">";
}
} else if (node.type() == pugi::node_pcdata) {
std::string text = node.value();
text.erase(0, text.find_first_not_of(" \t\n\r"));
text.erase(text.find_last_not_of(" \t\n\r") + 1);
if (!text.empty()) {
oss << text;
}
}
}
// 处理 <if> 标签并更新树结构
void process_if_node(pugi::xml_node if_node, pugi::xml_node &parent_node) {
std::string condition = if_node.attribute("condition").as_string();
bool condition_met = (condition == "true");
if (condition_met) {
// 如果条件满足,将子节点直接插入到父节点中
for (pugi::xml_node child = if_node.first_child(); child; child = child.next_sibling()) {
parent_node.insert_copy_before(child, if_node);
}
}
// 无论条件是否满足,都移除 <if> 节点
parent_node.remove_child(if_node);
}
void process_all_if_nodes(pugi::xml_node node);
void process_all_for_nodes(pugi::xml_node node);
// 处理 <for> 标签并展开它们
void process_for_node(pugi::xml_node for_node, pugi::xml_node &parent_node) {
int count = for_node.attribute("count").as_int();
if (count <= 0) {
std::cerr << "Invalid 'count' attribute" << std::endl;
return;
}
std::vector<pugi::xml_node> children_to_copy;
for (pugi::xml_node child : for_node.children()) {
children_to_copy.push_back(child);
}
for (int i = 0; i < count; ++i) {
for (pugi::xml_node child : children_to_copy) {
pugi::xml_node new_node = parent_node.insert_copy_before(child, for_node);
// 递归处理嵌套的 <for> 和 <if> 节点
process_all_if_nodes(new_node);
process_all_for_nodes(new_node);
}
}
// 最后移除 <for> 节点
parent_node.remove_child(for_node);
}
// 递归处理所有嵌套的 <if> 节点
void process_all_if_nodes(pugi::xml_node node) {
pugi::xml_node next_node;
for (pugi::xml_node child = node.first_child(); child; child = next_node) {
next_node = child.next_sibling();
if (std::string(child.name()) == "if") {
process_if_node(child, node);
} else {
process_all_if_nodes(child); // 递归调用
}
}
}
// 递归处理所有嵌套的 <for> 节点
void process_all_for_nodes(pugi::xml_node node) {
pugi::xml_node next_node;
for (pugi::xml_node child = node.first_child(); child; child = next_node) {
next_node = child.next_sibling();
if (std::string(child.name()) == "for") {
process_for_node(child, node);
} else {
process_all_for_nodes(child); // 递归调用
}
}
}
int docFrameContent(std::string input_path,std::string output_path){
pugi::xml_document doc;
// 加载 XML 文件
if (!doc.load_file(input_path.c_str())) {
std::cerr << "Failed to load XML file from " << input_path << std::endl;
return 1;
}
pugi::xml_node root = doc.child("root");
// 处理所有的 <if> 和 <for> 节点
process_all_if_nodes(root);
process_all_for_nodes(root);
// 创建一个格式化的字符串流
std::ostringstream oss;
oss << "<?xml version=\"1.0\"?>";
// 添加根节点的格式化
add_indentation(root, 0, oss);
// 保存格式化后的 XML 文件
std::ofstream output(output_path);
if (!output) {
std::cerr << "Failed to open the file " << output_path << std::endl;
return 1;
}
output << oss.str();
std::cout << "XML updated and formatted successfully." << std::endl;
return 0;
}
int main() {
// 设置文件路径
std::string input_path = "C:\\Users\\tirkl\\Desktop\\test\\input.xml";
std::string output_path = "C:\\Users\\tirkl\\Desktop\\test\\output.xml";
docFrameContent(input_path,output_path);
return 0;
}
输出的结果
<?xml version="1.0"?>
<root>
<item for="f1" if="f1i1">Outer Item
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
</item>
<item for="f1" if="f1i1">Outer Item
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
</item>
<item for="f1" if="f1i2">Outer Item
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
</item>
<item for="f1" if="f1i2">Outer Item
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
<subitem for="f2" if="f2i1">Inner Item 1
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
<subsubitem for="f3" if="f3i1">Innermost Item</subsubitem>
</subitem>
</item>
</root>