现在要用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