依据xml中for标签以及if标签动态构建xml

#输入的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>
### 回答1: mapper.xml的sql标签if是用于动态拼接SQL语句的标签。if标签的test属性用于判断条件是否成立,如果成立则执行if标签的SQL语句,否则不执行。if标签可以嵌套使用,用于构建复杂的SQL语句。if标签的使用可以提高SQL语句的灵活性和可读性。 ### 回答2: mapper.xml的sql标签if是MyBatis提供的一个条件判断标签,在SQL语句为我们提供了非常灵活的条件选择方式。if标签可以根据我们在mapper传递的参数值动态地生成不同的SQL语句,实现了动态SQL的功能。 if标签通常结合where标签使用,where标签是对SQL语句的一种筛选,只有where后的语句成立,此SQL语句才会被执行。if标签内可以包含多种判断条件,可以嵌套,可以利用OGNL表达式来实现动态SQL语句的构造。 使用if标签的最常见用法是对参数进行非空判断,这样可以防止SQL注入攻击,同时避免在SQL语句拼接字符串引起的性能问题。其次,我们可以根据不同的业务需求,选择不同的SQL语句来满足业务需求,提高系统的灵活性和可维护性。 在使用if标签时,需要注意可能会出现的逻辑错误和性能问题。在嵌套if标签时需要特别注意,容易出现条件判断错误。同时,在构造大量的if语句时,会影响SQL语句的性能。因此,我们需要在实际使用根据具体情况进行优化,尽量减少if标签的使用,提高SQL语句的效率。 总之,if标签是MyBatis非常重要的一个标签,可以实现非常灵活的条件判断和动态SQL语句的构造。使用时需要注意逻辑错误和性能问题,尽量减少if标签的使用,提高SQL语句的效率。 ### 回答3: 在MyBatis的mapper.xml文件,可以利用sql标签的if语句来进行动态SQL拼接。if语句可以判断某个条件是否为真,如果为真,则拼接对应的SQL语句,否则就不拼接。if语句在拼接SQL时十分有用,可以根据不同情况动态生成SQL语句。 使用if标签时,首先需要确定if语句的条件,条件可以是一个或多个查询参数或表达式。在if标签使用test属性来指定条件,test属性的属性值就是if语句的条件。test属性的值可以是一个表达式,MyBatis会将表达式的变量替换为参数值并计算表达式的结果来检查test属性所指定的条件是否为真。 如果test属性所指定的条件为真,则if标签的内容会被拼接到SQL语句;否则,if标签的内容就会被忽略掉。 下面是一个使用if标签的例子: ``` <select id="selectBlog" resultType="Blog"> SELECT * FROM blog <where> <if test="state != null"> AND state = #{state} </if> <if test="title != null and title != ''"> AND title LIKE #{title} </if> </where> ORDER BY create_time DESC </select> ``` 在上面的例子,我们使用了两个if标签动态生成SQL语句。第一个if标签判断查询参数state是否为非空,如果是,则拼接AND state = #{state}到SQL语句,否则忽略该标签的内容。第二个if标签则同时判断了查询参数title是否为非空和非空字符串,如果是,则拼接AND title LIKE #{title}到SQL语句,否则忽略该标签的内容。 使用if标签可以让我们动态生成SQL语句,减少程序硬编码的SQL语句的使用,从而让程序更加灵活和易于维护。因此,if标签是MyBatis非常重要的一个标签
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追Star仙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值