tinyxml2对换行符的处理

关于tinyxml2对换行符的处理

前段时间在项目上遇到了一个比较奇怪的问题,一串带有\r\nxml经过tinyxml2解析后,把\r\n解析成了\n,导致字符串不匹配。
后来拿出源码调试解析了一下,发现上在getText函数上进行了处理。

结论:

  • \r\n替换为\n
  • \r替换为\n
  • \n\r替换为\n

代码分析

XMLElement::GetText()

获取到当前元素的值,进node->Value()

const char* XMLElement::GetText() const
{
    /* skip comment node */
    const XMLNode* node = FirstChild();
    while (node) {
        if (node->ToComment()) {
            node = node->NextSibling();
            continue;
        }
        break;
    }

    if ( node && node->ToText() ) {
        return node->Value(); // 进value()
    }
    return 0;
}

XMLNode::Value()

const char* XMLNode::Value() const
{
    // Edge case: XMLDocuments don't have a Value. Return null.
    if ( this->ToDocument() )
        return 0;
    return _value.GetStr(); // 进GetStr()
}

StrPair::GetStr()

  • 可以看到当读到CR(\r)时,如果下一个字符时LF(\n)p指针直接跳过这两个字符,直接读取到后面的字符,并且将q指针置为\nq其实时p的一个前置指针;
  • 当读到\r时,但p + 1并不是\n,则p只跳过当前的\r,并且\r被指针q置成了\n;
  • 同样的在下一个if else分支中,\n\r也被处理成了\n;

同时可以看到在下一个if else分支对转义符号的处理,有兴趣的可以研究研究。

const char* StrPair::GetStr()
{
    TIXMLASSERT( _start );
    TIXMLASSERT( _end );
    if ( _flags & NEEDS_FLUSH ) {
        *_end = 0;
        _flags ^= NEEDS_FLUSH;

        if ( _flags ) {
            const char* p = _start;	// the read pointer
            char* q = _start;	// the write pointer

            while( p < _end ) {
                if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
                    // CR-LF pair becomes LF
                    // CR alone becomes LF
                    // LF-CR becomes LF
                    if ( *(p+1) == LF ) {
                        p += 2;
                    }
                    else {
                        ++p;
                    }
                    *q = LF;
                    ++q;
                }
                else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
                    if ( *(p+1) == CR ) {
                        p += 2;
                    }
                    else {
                        ++p;
                    }
                    *q = LF;
                    ++q;
                }
                else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
                    // Entities handled by tinyXML2:
                    // - special entities in the entity table [in/out]
                    // - numeric character reference [in]
                    //   &#20013; or &#x4e2d;

                    if ( *(p+1) == '#' ) {
                        const int buflen = 10;
                        char buf[buflen] = { 0 };
                        int len = 0;
                        const char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
                        if ( adjusted == 0 ) {
                            *q = *p;
                            ++p;
                            ++q;
                        }
                        else {
                            TIXMLASSERT( 0 <= len && len <= buflen );
                            TIXMLASSERT( q + len <= adjusted );
                            p = adjusted;
                            memcpy( q, buf, len );
                            q += len;
                        }
                    }
                    else {
                        bool entityFound = false;
                        for( int i = 0; i < NUM_ENTITIES; ++i ) {
                            const Entity& entity = entities[i];
                            if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
                                    && *( p + entity.length + 1 ) == ';' ) {
                                // Found an entity - convert.
                                *q = entity.value;
                                ++q;
                                p += entity.length + 2;
                                entityFound = true;
                                break;
                            }
                        }
                        if ( !entityFound ) {
                            // fixme: treat as error?
                            ++p;
                            ++q;
                        }
                    }
                }
                else {
                    *q = *p;
                    ++p;
                    ++q;
                }
            }
            *q = 0;
        }
        // The loop below has plenty going on, and this
        // is a less useful mode. Break it out.
        if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) {
            CollapseWhitespace();
        }
        _flags = (_flags & NEEDS_DELETE);
    }
    TIXMLASSERT( _start );
    return _start;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TinyXML-2 是一个开源的 C++ 库,主要用于解析和生成 XML,因此它也提供了对 XML 的序列化和反序列化功能。下面是一个简单的示例,演示如何使用 TinyXML-2 对 XML 进行序列化。 假设我们有一个 Person 类,它有两个属性 name 和 age: ```cpp class Person { public: std::string name; int age; Person(const std::string& name, int age) : name(name), age(age) {} }; ``` 我们想要将一个 Person 对象转换为 XML,可以按照以下步骤操作: 1. 导入头文件: ```cpp #include "tinyxml2.h" ``` 2. 创建一个 XML 文件: ```cpp tinyxml2::XMLDocument doc; ``` 3. 创建根元素: ```cpp auto root = doc.NewElement("Person"); doc.InsertEndChild(root); ``` 4. 将 Person 对象的属性添加到根元素中: ```cpp auto nameElem = doc.NewElement("name"); nameElem->SetText(person.name.c_str()); root->InsertEndChild(nameElem); auto ageElem = doc.NewElement("age"); ageElem->SetText(person.age); root->InsertEndChild(ageElem); ``` 5. 将 XML 保存到文件中: ```cpp doc.SaveFile("person.xml"); ``` 完整的代码示例如下: ```cpp #include <iostream> #include "tinyxml2.h" class Person { public: std::string name; int age; Person(const std::string& name, int age) : name(name), age(age) {} }; int main() { Person person("张三", 20); tinyxml2::XMLDocument doc; auto root = doc.NewElement("Person"); doc.InsertEndChild(root); auto nameElem = doc.NewElement("name"); nameElem->SetText(person.name.c_str()); root->InsertEndChild(nameElem); auto ageElem = doc.NewElement("age"); ageElem->SetText(person.age); root->InsertEndChild(ageElem); doc.SaveFile("person.xml"); return 0; } ``` 运行完上面的代码后,会在当前目录下生成一个名为 "person.xml" 的文件,其中包含以下内容: ```xml <?xml version="1.0"?> <Person> <name>张三</name> <age>20</age> </Person> ``` 这就是一个使用 TinyXML-2 对 XML 进行序列化的简单示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值