expat CharacterDataHandler使用

现在要用expat解析一段XML文档,网上看到很多使用expat的,大多数只是处理element的name,attribute,唯独不见text是如何处理的,刚好我的XML中没有用到attribute,所以针对XML_CharacterDataHandler的处理,从初步的理解到熟练使用还是破费了点事。

这里做一个简单的记录。

我的XML文档:
<?xml version="1.0" encoding="UTF-8"?>
<Marker>
    <MarkerName>subtype:caption</MarkerName>
    <Parameters>
        <Parameter>
            <Name>data,en-US</Name>
            <Type>String</Type>
            <Value> CONTINUE TO PLAY </Value>
        </Parameter>
    </Parameters>
</Marker>

XML_SetCharacterDataHandler  注册 了文本数据   handle ,在expat的sample中并没有使用这个函数,通过debug得知,这个函数在element开始和结束的时候都会被调用。

XML_CharacterDataHandler的函数声明:
typedef void
(*XML_CharacterDataHandler)(void *userData,
                            const XML_Char *s,
                            int len);

element开始的时候,如果有文本数据,XML_CharacterDataHandler函数的s参数就是element的文本内容,需要通过len参数得到具体的长度,不然s就是当前文本后面的xml文档剩余部分。

element结束的时候,通过调试,我发现len的长度虽然大于0, 但是包含一个'\n'(因为我的XML文档里面element开始结束的<>后面我都加了换行),所以在我后面的代码中我将'\n'过滤掉了,不然text得到的数据还会有只有一个'\n'的情况。

    if ((len > 0) && (*s != '\n')) {
        text = AString(s, len);
    }

上面这几行代码就得到了text部分的文本。

注意:

  • 开始看到这个函数的时候,看到有人说什么处理字符集的,容易被误导,这个函数就是处理XML的文本数据的。
  • 通过userData参数得到depth似乎不能工作,参考sample.c中的int *depth = userData,然后操作depth都会导致crash。我的做法是在外部定义一个de全局的depth变量,startElement中加一 ,endElement减一。

下面是我的XML解析过程LOG信息:

 parse ID3 PRIV XML, created xml parser.
 parsed element : Marker, depth : 0
 parsed element : MarkerName, depth : 1
 parsed MarkerName's  text data : subtype:caption
 element MarkerName's text is subtype:caption
 parsed element : MarkerName, depth : 0
 parsed element : Parameters, depth : 1
 parsed element : Parameter, depth : 2
 parsed element : Name, depth : 3
 parsed Name's  text data : data,en-US
 parsed element : Name, depth : 2
 parsed element : Type, depth : 3
 parsed Type's  text data : String
 parsed element : Type, depth : 2
 parsed element : Value, depth : 3
 parsed Value's  text data :  CONTINUE TO PLAY
 caption text is :  CONTINUE TO PLAY
 parsed element : Value, depth : 2
 parsed element : Value, depth : 1
 parsed element : Value, depth : 0

可以看的出来我的xml的text数据都被正确解析出来了,下面是XML_CharacterDataHandler的实现:

privDataHandle(void *, char *s, int len)
{
    AString text;
    int curDepth = mXmlDepth - 1;

    if (mParsedStatus != OK) return;

    LOGV("parsed element : %s, depth : %d", mCurElementName.c_str(), curDepth);

    if ((len > 0) && (*s != '\n')) {
        text = AString(s, len);
        LOGV("parsed %s's text data : %s\n", mCurElementName.c_str(), text.c_str());
    }

    switch (curDepth) {
        case 0:
            break;
        case 1:
            if (mCurElementName == AString("MarkerName")) {
                if ((text == AString("subtype:caption"))) {
                    LOGV("element MarkerName's text is subtype:caption ");
                } else {
                    LOGE("element MarkerName's text is not subtype:caption ");
                    mParsedStatus = -EINVAL;
                }
            }
            break;
        case 2:
            break;
        case 3:
            if (mCurElementName == AString("Value")) {
                LOGV("caption text is : %s", text.c_str());
            }
            break;
        default:
            break;
    }
}

Reference:

  • http://www.cnblogs.com/Tue/archive/2010/01/18/1650258.html
  • http://book.luaer.cn/_164.htm
  • http://www.xml.com/pub/a/1999/09/expat/index.html
  • http://blog.csdn.net/caimouse/article/details/2455644[对 XML_CharacterDataHandler 描述是错误的]
  • http://blog.csdn.net/Aresky/article/details/353356



你可能感兴趣的:(expat CharacterDataHandler使用)