版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Matthew_Fan/article/details/8448136
接上文,上文中提到获取网络直播电视地址的方法,但是大量信息需要人工的方式进行处理,过于麻烦。所以本文针对三级的XML解析和下载工作进行处理。
技术点:1、利用tinyXML完成XML的解析工作 tinyxml下载
2、利用libcurl完成xml的下载工作 libcurl下载
公用下载函数:
// 下载相关的XML
static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
{
size_t nsize=size*nmemb;
//…在这里保存数据
string *strHtml=(string*)userp;
strHtml->append((char*)buffer,nsize);
return nsize;
}
bool downloadXml(const char* fileUrl, string& xmlStr)
{
if ("" == fileUrl)
{
dxreport("downloadXml: fileUrl is empty ...");
return false;
}
xmlStr = ""; // 清空缓存XML
CURL* m_curl = curl_easy_init();
if (NULL == m_curl)
{
dxreport("downloadXml: create curl fail ...");
return false;
}
string* str = new string();
curl_easy_reset(m_curl); //主要是在重复调用GET/POST时,清空curl中的设置
curl_easy_setopt(m_curl, CURLOPT_URL, fileUrl);
curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA,(void *)str);
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, write_data);
CURLcode res = curl_easy_perform(m_curl);
curl_easy_cleanup(m_curl);
if (res != CURLE_OK || str->length() == 0)
{
dxreport("downloadXml: download xml fail! url = %s", fileUrl);
cout << fileUrl << endl;
return false;
}
xmlStr = *str;
return true;
}
解析第一级XML:
<?xml version="1.0" encoding="UTF-8"?>
<atv>
<body>
<listScrollerSplit id="com.sample.list-scroller-split">
<header>
<simpleHeader>
<title>电视直播</title>
</simpleHeader>
</header>
<menu>
<sections>
<menuSection>
<header>
<textDivider alignment="left">
<title>类别选择</title>
</textDivider>
</header>
<items>
<oneLineMenuItem id="list_1">
<label>央视直播</label>
<preview>
<link>http://atv.jianguoke.com/appletv/tv/list_1.xml</link>
</preview>
</oneLineMenuItem>
</items>
</menuSection>
</sections>
</menu>
</listScrollerSplit>
</body>
</atv>
样例XML如上所示,现在我们开始解析工作。
// 解析第一级XML
bool parseFristXml(const char* fileName, list<CHANNEL_INFO>& listChannel)
{
string strXml = "";
if (false == downloadXml(fileName, strXml))
{
return false;
}
TiXmlDocument* document = new TiXmlDocument();
if (false == document->Parse(strXml.c_str()))
{
return false;
}
/*TiXmlDeclaration *decl;
decl = document->FirstChild()->ToDeclaration();*/
// 查找到根部
TiXmlElement* rootElement = document->RootElement();
TiXmlElement* keyBody = rootElement->FirstChildElement();
TiXmlElement* keyListScrollerSplit = keyBody->FirstChildElement();
TiXmlElement* keyHeadFrist = keyListScrollerSplit->FirstChildElement();
TiXmlElement* keyMenu = keyHeadFrist->NextSiblingElement();
if (keyMenu == NULL)
{
return false;
}
// 进入到menu中
TiXmlElement* keySections = keyMenu->FirstChildElement();
TiXmlElement* keySectionsMenu = keySections->FirstChildElement();
TiXmlElement* keySectionsHeaderMenu = keySectionsMenu->FirstChildElement();
TiXmlElement* keySectionsItems = keySectionsHeaderMenu->NextSiblingElement(); // 发现解析头部
TiXmlElement* item = keySectionsItems->FirstChildElement(); // 取得第一个标签
while (item)
{
CHANNEL_INFO info;
TiXmlElement* oneLineMenuItem = item->FirstChildElement(); // 获取lable的内容
info.name = changeTxtEncoding(oneLineMenuItem->GetText());
oneLineMenuItem = oneLineMenuItem->NextSiblingElement()->FirstChildElement();
info.fileUrl = oneLineMenuItem->GetText();
listChannel.push_back(info); // 存储数据
item = item->NextSiblingElement(); // 切到下个标记
}
return true;
}
tinyXML函数的具体使用在这里就不累赘了,针对TinyXML解析方法可参见博客的其他相关内容。
解析第二级XML:
<?xml version="1.0" encoding="UTF-8"?>
<atv>
<head>
<script src="http://atv.jianguoke.com/appletv/video.js"/>
</head>
<body>
<preview>
<scrollerPreview id="com.sample.scrollerPreview">
<items>
<grid id="grid_1" columnCount="5">
<items>
<sixteenByNinePoster id="type1_1" alwaysShowTitles="true" accessibilityLabel="" onHoldSelect="savevideofav('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/img/m_cctv1.png', 'CCTV-1 综合', '5')" onSelect="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'CCTV-1 综合', '5')" onPlay="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'CCTV-1 综合', '5')">
<title>CCTV-1 综合</title>
<image>http://atv.jianguoke.com/appletv/tv/img/m_cctv1.png</image>
<defaultImage>resource://Poster.png</defaultImage>
</sixteenByNinePoster>
<sixteenByNinePoster id="type1_2" alwaysShowTitles="true" accessibilityLabel="" onHoldSelect="savevideofav('http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'http://atv.jianguoke.com/appletv/tv/img/m_cctv2.png', 'CCTV-2 财经', '5')" onSelect="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'CCTV-2 财经', '5')" onPlay="playvideo('http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_2.xml', 'CCTV-2 财经', '5')">
<title>CCTV-2 财经</title>
<image>http://atv.jianguoke.com/appletv/tv/img/m_cctv2.png</image>
<defaultImage>resource://Poster.png</defaultImage>
</sixteenByNinePoster>
</items>
</grid>
</items>
</scrollerPreview>
</preview>
</body>
</atv>
处理函数为:
// 解析第二级XML
bool parseSecondXml(list<CHANNEL_INFO> fristXmlChannel, list<CHANNEL_INFO>& secondXmlChannel)
{
int len = fristXmlChannel.size();
if (len == 0)
{
dxreport("parseSecondXml: get fristXmlChannel is empty!");
return false;
}
for (int i = 0; i < len; i++)
{
CHANNEL_INFO info;
list<CHANNEL_INFO>::iterator iter = fristXmlChannel.begin();
info = (*iter);
fristXmlChannel.pop_front(); // 清除头部的数据
string strXml = "";
if (false == downloadXml(info.fileUrl.c_str(), strXml))
{
continue;
}
// 进行二级解析XML
TiXmlDocument* document = new TiXmlDocument();
if (false == document->Parse(strXml.c_str()))
{
return false;
}
TiXmlElement* element = document->RootElement();
element = element->FirstChildElement();
element = element->NextSiblingElement(); // body
for (int i = 0; i < 6; i++)
{
element = element->FirstChildElement();
}
// 获取三级XML下载地址
while (element)
{
TiXmlAttribute* attribute = element->FirstAttribute();
while (attribute)
{
string keyName = attribute->Name();
if (keyName == "onPlay")
{
// 获取到的内容如下格式:
//"playvideo('http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'http://atv.jianguoke.com/appletv/tv/live_1_1.xml', 'CCTV-1 综合', '5')"
string strContent = attribute->Value();
// 解析字符串
int len = strContent.length();
string keyStr[4] = {"", "", "", ""};
string str = "";
int keyNum = 0;
for (int i = 0; i < len; i ++)
{
if (strContent[i] == '\'')
{
if (strContent[i+1] == ',')
{
keyStr[keyNum] = str;
keyNum ++;
}
str = "";
continue;
}
str += strContent[i];
}
// 存储数据
CHANNEL_INFO newInfo;
newInfo.fileUrl = keyStr[0];
newInfo.name = changeTxtEncoding(keyStr[2].c_str());
secondXmlChannel.push_back(newInfo);
}
attribute = attribute->Next();
}
element = element->NextSiblingElement();
}
}
return true;
}
解析第三级XML:
<?xml version="1.0" encoding="UTF-8"?>
<atv>
<body>
<videoPlayer id="com.sample.video-player">
<httpFileVideoAsset id="live_3_5">
<mediaURL>http://182.140.144.32:8080/playlist/37.m3u8?key=rkH0PG-pfffEkcMUDSZoEwbswucCuObIj1fYeg..</mediaURL>
<title/>
<description/>
<image/>
</httpFileVideoAsset>
</videoPlayer>
</body>
</atv>
解析函数:
// 解析最后一级XML
bool parseEndXml(list<CHANNEL_INFO> secondXmlChannel, list<CHANNEL_INFO>& endXmlChannel)
{
int len = secondXmlChannel.size();
if (len == 0)
{
dxreport("parseSecondXml: get fristXmlChannel is empty!");
return false;
}
for (int i = 0; i < len; i++)
{
CHANNEL_INFO info;
list<CHANNEL_INFO>::iterator iter = secondXmlChannel.begin();
info = (*iter);
secondXmlChannel.pop_front(); // 清除头部的数据
string strXml = "";
if (false == downloadXml(info.fileUrl.c_str(), strXml))
{
continue;
}
// 进行三级级解析XML
TiXmlDocument* document = new TiXmlDocument();
if (false == document->Parse(strXml.c_str()))
{
return false;
}
TiXmlElement* element = document->RootElement();
for (int i = 0; i < 4; i++)
{
element = element->FirstChildElement();
}
CHANNEL_INFO newInfo;
newInfo.fileUrl = element->GetText();
newInfo.name = info.name;
endXmlChannel.push_back(newInfo);
cout << newInfo.name << ":" << newInfo.fileUrl << endl;
}
return true;
}
以上就是相关处理内容。望给各位有所帮助 ....