c++ - 如何使用 RapidXML C++ 检查 xml 中的空标记

标签 c++ xml xml-parsing rapidxml

存在 XML:

<?xml version="1.0" encoding="UTF-8"?>
<ServerData>
    <NetJobChunk id="599">
        <Frames>0.000 - 0.000</Frames>
        <EndTime>0</EndTime>
        <ChunkID>1</ChunkID>
        <StartDateTime>42212.713495</StartDateTime>
        <RenderedFiles></RenderedFiles>
        <AttemptsText>0</AttemptsText>
        <RenderingTimeText>n/a</RenderingTimeText>
        <Slice>Entire image</Slice>
        <Attempts>0</Attempts>
        <ErrorCount>0</ErrorCount>
        <StartDateText>27.07.2015 17:07:26</StartDateText>
        <RenderingClient></RenderingClient>
        <Priority>0</Priority>
        <StartTime>0</StartTime>
        <NetJobID>599</NetJobID>
        <ExtSplitting>None</ExtSplitting>
        <AvgCPUUsage>0.000000</AvgCPUUsage>
        <RenderingClientUuid>00000000-0000-0000-0000-000000000000</RenderingClientUuid>
        <History></History>
        <CacheScenesLocally>false</CacheScenesLocally>
        <RenderingTime>0</RenderingTime>
        <RecacheScenes>false</RecacheScenes>
        <StateMachineState>0</StateMachineState>
        <Scene>P:\\ftpuser\\F20141088\\Scene_news\\3dsmax\\test.max</Scene>
        <StatusText>Done</StatusText>
        <Status>4</Status>
    </NetJobChunk>

    <NetJobChunk id="599">
        <Frames>1.000 - 1.000</Frames>
        <EndTime>0</EndTime>
        <ChunkID>2</ChunkID>
        <StartDateTime>42212.713495</StartDateTime>
        <RenderedFiles></RenderedFiles>
        <AttemptsText>0</AttemptsText>
        <RenderingTimeText>n/a</RenderingTimeText>
        <Slice>Entire image</Slice>
        <Attempts>0</Attempts>
        <ErrorCount>0</ErrorCount>
        <StartDateText>27.07.2015 17:07:26</StartDateText>
        <RenderingClient></RenderingClient>
        <Priority>0</Priority>
        <StartTime>0</StartTime>
        <NetJobID>599</NetJobID>
        <ExtSplitting>None</ExtSplitting>
        <AvgCPUUsage>0.000000</AvgCPUUsage>
        <RenderingClientUuid>00000000-0000-0000-0000-000000000000</RenderingClientUuid>
        <History></History>
        <CacheScenesLocally>false</CacheScenesLocally>
        <RenderingTime>0</RenderingTime>
        <RecacheScenes>false</RecacheScenes>
        <StateMachineState>0</StateMachineState>
        <Scene>P:\\ftpuser\\F20141088\\Scene_news\\3dsmax\\test.max</Scene>
        <StatusText>Done</StatusText>
        <Status>4</Status>
    </NetJobChunk>

    <NetJobChunk id="601">
        <Frames>0.000 - 0.000</Frames>
        <EndTime>0</EndTime>
        <ChunkID>1</ChunkID>
        <StartDateTime>42212.852882</StartDateTime>
        <RenderedFiles></RenderedFiles>
        <AttemptsText>1 (max)</AttemptsText>
        <RenderingTimeText>n/a</RenderingTimeText>
        <Slice>Entire image</Slice>
        <Attempts>1</Attempts>
        <ErrorCount>1</ErrorCount>
        <StartDateText></StartDateText>
        <RenderingClient></RenderingClient>
        <Priority>0</Priority>
        <StartTime>0</StartTime>
        <NetJobID>601</NetJobID>
        <ExtSplitting>Camera: 005</ExtSplitting>
        <AvgCPUUsage>0.000000</AvgCPUUsage>
        <RenderingClientUuid>00000000-0000-0000-0000-000000000000</RenderingClientUuid>
        <History>
            <Value>1|1437999253|Rendering started [RENDERHOST202]|</Value>
            <Value>4|1438010887|27.07.2015 20:28:07;  Error rendering frame 0: An unexpected exception has occurred in the network renderer and it is terminating.|</Value>
            <Value>4|1438010888|Chunk error: The renderer returned an error-code (0x3) [RENDERHOST202]|</Value>
            <Value>1|1438010889|Rendering started [RENDERHOST202]|</Value>
            <Value>3|1438017456|Chunk cancelled [RENDERHOST202]|</Value>
            <Value>3|1438017456|Net Job cancelled by user|</Value>
        </History>
        <CacheScenesLocally>false</CacheScenesLocally>
        <RenderingTime>0</RenderingTime>
        <RecacheScenes>false</RecacheScenes>
        <StateMachineState>0</StateMachineState>
        <Scene>P:\\ftpuser\\F20131020\\2House_22_2015_07_27_12_16_55\\2House_22.max</Scene>
        <StatusText>Cancelled</StatusText>
        <Status>5</Status>
    </NetJobChunk>

</ServerData>

要求接收标签“History”最后一次事件的最大值时间(以滴答为单位):

<History>
   <Value>...</Value>
</History>.

标签“历史”可以为空:

<History></History>.

解析:

...
char* ch = new char[xml.size()+1];
std::copy(xml.begin(), xml.end(), ch);
ch[xml.size()] = '\0';

xml_document<char> doc;
doc.parse<0>(ch);
unsigned long LastEventTime = 0;

xml_node<> *root_node = doc.first_node("ServerData");
for (xml_node<> * chunk_node = root_node->first_node("NetJobChunk"); chunk_node; chunk_node = chunk_node->next_sibling())
{
    // History
    unsigned long result = ParseChunkLastEventTime(chunk_node);
    if(result > LastEventTime)
        LastEventTime = result;

}

...

unsigned long CRapidXmlParser::ParseChunkLastEventTime(xml_node<char>* chunk_node) {
    unsigned long val = 0;
    if(chunk_node == nullptr)
        throw std::exception("ParseChunkLastEventTime: null ptr chunk_node");

    xml_node<> * chunk_hist_node = chunk_node->first_node("History");
    xml_node<> * last_value_node = chunk_hist_node->last_node("Value");// ERROR!!!
    if(last_value_node) {
        std::string last_event = last_value_node->value();
        size_t time_begin = last_event.find_first_of('|');
        if(time_begin != std::string::npos) {
            size_t time_end = last_event.find_first_of('|', time_begin+1);
            if(time_end != std::string::npos) {
                val = boost::lexical_cast<unsigned long>(last_event.substr(time_begin+1, time_end-time_begin-1) );
            }
        } 
    }

    return val;
}

当我尝试获取空标签“History”的最后一个子标签(“Value”)时 - 我得到一个异常,而不是预期的空指针。有什么问题?

最佳答案

需要使用first_node(),检查节点是否有子节点。

unsigned long CRapidXmlParser::ParseChunkLastEventTime(xml_node<char>* chunk_node) {
    unsigned long val = 0;
    if(chunk_node == nullptr)
        throw std::exception("ParseChunkLastEventTime: null ptr chunk_node");

    xml_node<> * chunk_hist_node = chunk_node->first_node("History");
    if(chunk_hist_node->first_node("Value")) {
        xml_node<> * last_value_node = chunk_hist_node->last_node("Value");
        if(last_value_node) {
            std::string last_event = last_value_node->value();
            size_t time_begin = last_event.find_first_of('|');
            if(time_begin != std::string::npos) {
                size_t time_end = last_event.find_first_of('|', time_begin+1);
                if(time_end != std::string::npos) {
                    val = boost::lexical_cast<unsigned long>(last_event.substr(time_begin+1, time_end-time_begin-1) );
                }
            } 
        }
    }

    return val;
}

关于c++ - 如何使用 RapidXML C++ 检查 xml 中的空标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31847084/

相关文章:

java - 修改java文件夹中的xml文件

java - 返回空 NodeList 的命名空间感知文档

c# - 反序列化复杂对象中的 xml

c++ - 使用 pugixml 和 C++ 向 .xml 添加行

java - 缺少依赖项版本 - io.vertx :vertx-stack-depchain:jar is missing 为 'dependencies.dependency.version'

c++ - 将宏转换为函数

c# - 将 C# 表单序列化为 XML

python - 使用命名空间解析 XML 时出现问题

c++ - 我能以某种方式不写出完整的限定返回类型名称吗?

c++ - 需要 Qt 架构建议