其实说的都不错,但是对libxml2库的理解狭隘了一点。

libxml2现在不仅仅可以解析XML(EXtensible Markup Language)格式,包括HTML(HyperText Markup Language)以及现时常用的超文本格式的最高层次标准 SGML(Standard Generalized Markup Language) 都可以解析。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <string>
#include <libxml/parser.h>

#define BUFFERSIZE 1024 * 1024 * 3
#define READALINE 1024 * 1024 * 1

using namespace std;

int main(int argc, char *argv[])
{
    if (argc != 2) {
        printf("Usgae: %s <Url or File>\n", argv[0]);
        exit(0);
    }
    char *file = argv[1];
    xmlParserCtxtPtr ctxt;
    xmlDocPtr doc;
    xmlNodePtr cur;
    // 创建一个Parser
    ctxt = xmlNewParserCtxt();
    // 读取链接流或文件流
    doc = xmlCtxtReadFile(ctxt, file, "GBK", XML_PARSE_DTDATTR|XML_PARSE_NOERROR);
    if (doc == NULL) {
        printf("Can't parse the content: %s\n", file);
        return 0;
    }
    // 获取根节点,此时的根节点可以通过cur->name获取
    cur = xmlDocGetRootElement(doc);
    if (cur == NULL) {
        printf("Can't get the root element: %s\n", file);
        xmlFreeDoc(doc);
        xmlFreeParserCtxt(ctxt);
        return 0;
    }
    // 获取子节点,此时的子节点也可以通过cur->name获取
    while (cur != NULL) {
        if (!xmlStrcmp(cur->name, (const xmlChar *)"news")){
            xmlChar *key;
            // 继续获取下个子节点的字节点
            xmlNodePtr l_cur = cur->xmlChildrenNode;
            while (l_cur != NULL) {
                if (!xmlStrcmp(l_cur->name, (const xmlChar *)"title")) {
                    key = xmlNodeListGetString(doc, l_cur->xmlChildrenNode, 1);
                    printf("title: %s\n", key);
                    xmlFree(key);
                } else if (!xmlStrcmp(l_cur->name, (const xmlChar *)"content")) {
                    key = xmlNodeListGetString(doc, l_cur->xmlChildrenNode, 1);
                    printf("content: %s\n", key);
                    xmlFree(key);
                }
                l_cur = l_cur->next;
            }
        }
        // 继续获取下个子节点
        cur = cur->next;
    }

// 释放资源,很多网上的教程是没有释放资源或者释放得不彻底
    xmlFreeDoc(doc);
    xmlFreeParserCtxt(ctxt);
    xmlCleanupParser();
    return 0;
}
2,libxml2解析字符流(结合libcurl)
其实libxml2可以通过xmlCtxtReadMemory等函数进行解析,但是这个流必须是标准的xml格式,应用范围相对狭隘一些,这里结合libcurl来获取<a href=""></a>中的url信息:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <curl/curl.h>
#include <libxml/HTMLparser.h>

using namespace std;

#ifdef _MSC_VER
#define COMPARE(a, b) (!stricmp((a), (b)))
#else
#define COMPARE(a, b) (!strcasecmp((a), (b)))
#endif

typedef struct LinkStringDefined
{
    string url;
    string anthor_text;
} LinkString;

typedef struct ContextDefined
{
    ContextDefined(): addTitle(false) { }
    bool addTitle;
    string title;
    string url;
    vector<LinkString> terms;
} Context;

static char errorBuffer[CURL_ERROR_SIZE];
static string buffer;
static int writer(char *, size_t, size_t, string *);
static bool init(CURL *&, char *);
static void parseHtml(const string &, vector<LinkString> &);
static void StartElement(void *, const xmlChar *, const xmlChar **);
static void EndElement(void *, const xmlChar *);
static void Characters(void *, const xmlChar *, int);
static void CdataBlock(void *, const xmlChar *, int);

int main(int argc, char* argv[])
{
    CURL *conn = NULL;
    CURLcode code;
    vector<LinkString> arr;
    if (argc != 2 && argc != 3)
    {
        fprintf(stderr, "Usage: %s <url> <null>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    curl_global_init(CURL_GLOBAL_DEFAULT);
    if (!init(conn, argv[1]))
    {
        fprintf(stderr, "Connection initializion failed\n");
        exit(EXIT_FAILURE);
    }
    code = curl_easy_perform(conn);
    curl_easy_cleanup(conn);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "Failed to get '%s' [%s]\n", argv[1], errorBuffer);
        exit(EXIT_FAILURE);
    }
    parseHtml(buffer, arr);
    int arr_size = arr.size();
    for(int i = 0; i < arr_size; i ++)
    {
        cout << arr[i].anthor_text << "\t" << arr[i].url << endl;
    }
    return 0;
}

static bool init(CURL *&conn, char *url)
{
    CURLcode code;
    conn = curl_easy_init();
    if (conn == NULL)
    {
        fprintf(stderr, "Failed to create CURL connection\n");
        exit(EXIT_FAILURE);
    }
    code = curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "Failed to set error buffer [%d]\n", code);
        return false;
    }
    code = curl_easy_setopt(conn, CURLOPT_URL, url);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "Failed to set URL [%s]\n", errorBuffer);
        return false;
    }
    code = curl_easy_setopt(conn, CURLOPT_FOLLOWLOCATION, 1);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "Failed to set redirect option [%s]\n", errorBuffer);
        return false;
    }
    code = curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writer);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "Failed to set writer [%s]\n", errorBuffer);
        return false;
    }
    code = curl_easy_setopt(conn, CURLOPT_WRITEDATA, &buffer);
    if (code != CURLE_OK)
    {
        fprintf(stderr, "Failed to set write data [%s]\n", errorBuffer);
        return false;
    }
    return true;
}

static int writer(char *data, size_t size, size_t nmemb, string *writerData)
{
    unsigned long long sizes = size * nmemb;
    if (writerData == NULL) return 0;
    writerData->append(data, sizes);
    return sizes;
}

// 关键点:自己可以定义节点形式(开始和结束位置)
static htmlSAXHandler saxHandler =
{
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    StartElement,
    EndElement,
    NULL,
    Characters,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    CdataBlock,
    NULL
};

static void parseHtml(const string &html, vector<LinkString> &arr)
{
    htmlParserCtxtPtr ctxt;
    Context context;
    ctxt = htmlCreatePushParserCtxt(&saxHandler, &context, "", 0, "", XML_CHAR_ENCODING_NONE);
    htmlParseChunk(ctxt, html.c_str(), html.size(), 0);
    htmlParseChunk(ctxt, "", 0, 1);
    htmlFreeParserCtxt(ctxt);
    arr = context.terms;
}

static void StartElement(void *voidContext, const xmlChar *name, const xmlChar **attributes)
{
//  int sz_att = sizeof(**attributes) / sizeof(xmlChar);
    Context *context = (Context *)voidContext;
    if (COMPARE((char *)name, "a"))
    {
        context->url = (char *)attributes[1];
        context->title = "";
        context->addTitle = true;
    }
}

static void EndElement(void *voidContext, const xmlChar *name)
{
    Context *context = (Context *)voidContext;
    if (COMPARE((char *)name, "a"))
    {
        context->url = "";
        context->addTitle = false;
    }
}

static void handleCharacters(Context *context, const xmlChar *chars, int length)
{
    LinkString linkString;
    if (context->addTitle)
    {
        context->title.append((char *)chars, length);
        linkString.anthor_text = context->title;
        linkString.url = context->url;
        context->terms.push_back(linkString);
    }
}

static void Characters(void *voidContext, const xmlChar *chars, int length)
{
    Context *context = (Context *)voidContext;
    handleCharacters(context, chars, length);
}

static void CdataBlock(void *voidContext, const xmlChar *chars, int length)
{
    Context *context = (Context *)voidContext;
    handleCharacters(context, chars, length);
}

关于libxml2就先介绍到这,其实这里面还有很多很多的小技巧,还需要各位去挖掘哟~! :)

http://my.huhoo.net/archives/2009/01/libxml2.html

如何使用libxml2库[转]相关推荐

  1. Python3.x(windows系统)安装libxml2库

    Python3.x(windows系统)安装libxml2库 cmd安装命令: pip install lxml 执行结果: 再执行命令: pip install virtualenv 执行结果: 转 ...

  2. XML编程经验――LIBXML2库使用指南

    C++的XML编程经验――LIBXML2库使用指南 写这篇文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML ...

  3. linux下libxml2库使用说明

    linux下libxml2库使用说明_lanlicen的专栏-CSDN博客_linux xml库 第一章 什么是XML? 1.xml简介 XML(Extensible Markup Language) ...

  4. C++的XML编程经验――LIBXML2库使用指南

    写这篇文章的原因有如下几点: 1)C++标准库中没有操作XML的方法,用C++操作XML文件必须熟悉一种函数库,LIBXML2是其中一种很优秀的XML库,而且它同时支持多种编程语言: 2)LIBXML ...

  5. XML---(2)LIBXML2库Linux使用指南

    libxml(一)                                      摘要 Libxml是一个有免费许可的用于处理XML.可以轻松跨越多个平台的C语言库.这个指南提供它的基本函 ...

  6. C语言-XLSX基础数据解析(需借助libxml2库)

    一.背景:公司要从FPT上下载一些数据文件,主要有XLS,XLSX,CSV三种文件,XLS的解析用了第三方库libxls 请看链接 C语言接口libxls使用_skv00d00的博客-CSDN博客 至 ...

  7. libxml2 c库使用

    ##libxml2库 1.读取一个文件到内存 xmlParseFile和xmlReadFile:xmlReadFile() is a bit more powerful as it is able t ...

  8. libxml2 libxslt库编译

    libxml2官方下载地址:点击打开链接我下载的版本是2.9.3 libxslt官方下载地址:点击打开链接我下载的版本是1.1.29 一.编译libxml2-2.9.3(32位) 1. iconv库准 ...

  9. libxml2中处理中文

    在上篇中简单介绍了libxml2读写XML文件. 本篇将介绍如何在libxml2中读写中文数据. libxml2中提供了编解码器,通过建立自己的编码接口由libxml根据当前编码进行调用,实质上是使用 ...

最新文章

  1. R语言包_plotly
  2. matplotlib中plot的颜色
  3. java 对象读写_java 对象输入输出流读写文件的操作实例
  4. Not so Mobile(二叉树递归输入同时建树){天平}
  5. 联想战略储备看创投,联想创投All in智能互联网
  6. hadoop 主要配置文件
  7. 运营商大数据有哪些好处
  8. sd卡写保护解除工具_手把手教你快速解除vivo手机高通系列屏幕锁(附短接拆机小视频)...
  9. PMP备考经验分享 制表很重要
  10. mysql横向扩展_转mysql横向扩展和纵向扩展
  11. Nginx--Rewrite重写
  12. Sql server AlwaysOn搭建常见问题
  13. java wrap()_Java中的CharBuffer wrap()方法
  14. 《数据库原理及应用教程》考试系统
  15. 网络图片版权保护的主要问题
  16. oracle服务自己停止工作,求救:ORACLE服务自动停止!
  17. Cadence OrCAD Capture 原理图中预览元件封装技巧图文教程
  18. 怎样持续不断的学习~~
  19. MATLAB图像处理与计算机视觉(2):在图像上取点划线
  20. mysql新旧版本_MySQL新旧版本ORDER BY 处理方法

热门文章

  1. 用ABC三个字母简洁归纳2018年物联网趋势
  2. 查找CSDN误删除博客方法
  3. Azure SQL性能调优实践
  4. 一起来玩AZURE SQL(三)AZURE SQL 数据库迁移
  5. 男人必读:女人64个谜团
  6. 转载一篇杨澜的演讲稿——关于孩子的想象力创造力
  7. 上海市消保委:春节长假期间 共受理消费者投诉4600件
  8. 京东方计划为苹果iPhone 13供应6.06英寸OLED面板
  9. 包装又缩水!iPhone 13包装盒塑料膜变纸质拉条 网友:要将环保进行到底?
  10. 团建之后,我想离职了