xml基础

一.XML基础

1.XML简介

  • XML是指可扩展标记语言(Extensible Markup Language),它是一种标记语言,很类似HTML。它被设计的初衷是为了替换html,但没有替换成功,所以就退居幕后,常用作配置文件。
  • XML标签没有被预定义,需要用户自行定义标签。
  • XML技术是W3C组织(World Wide Web Consortium万维网联盟)发布的,目前遵循的是W3C组织于2000年发布的XML10规范。

2.XML常见应用

  • 用于软件/框架的配置文件
  • 保存数据
  • 传输\交换数据

二.XML文件格式

1.文档声明

XML文件的第一行必须是文档声明,即使是注释或空格等无意义的内容也会报错。

<?xml version="1.0" encoding="utf-8"?>
  • version (必须要有) :表示xml的版本1.0 1.1(要是有10,因为1.1版本不会向下兼容)
  • encoding (可选) : xml 档的编码方式 utf-8、gbk (gb2312 gb2310)、 iso8859-1(不支持中文)

2.根标签

即使你把上面的文档声明放在第一行,用浏览器打开也还是会报错,这是因为我们一般在文档声明的第二行我们一般会跟上根标签。

三.XML标签定义

1.标签定义

  • 1.XML文件只能有一个跟标签
  • 2.标签自定义,也可以是中文
  • 3.标签无论是成对的还是自闭合的,有开始也有结束

2.标签命名规范

  • 1.区分大小写,标签签后必须一致
  • 2.标签不能以数字和下划线开头
  • 3.不能以xml开始
  • 4.不能包含空格
  • 5.中间不能包含冒号

注意:XML解析的时候会把空格和换行都当作内容来处理

3.标签属性

  • 1.每个自定义标签可以有多个属性,但不能相同
  • 2.属性与属性值之间使用引号

4.注释

  • 格式:<-- xml注释 -->
  • 注释中间不能嵌套

四.补充

1.转义字符

我们知道标签是用大于和小于号定义的

<            &lt;
>            &gt;
&            &amp;
"            &quot;
'            &apos;

2.CDATA

术语 CDATA 指的是不应由 XML 解析器进行解析的文本数据(Unparsed Character Data)。

在 XML 元素中,"<" 和 "&" 是非法的。

"<" 会产生错误,因为解析器会把该字符解释为新元素的开始。

"&" 也会产生错误,因为解析器会把该字符解释为字符实体的开始。

某些文本,比如 JavaScript 代码,包含大量 "<" 或 "&" 字符。为了避免错误,可以将脚本代码定义为 CDATA。

CDATA 部分中的所有内容都会被解析器忽略。

CDATA 部分由 "" 结束:

<script>
<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then
  {
  return 1;
  }
else
  {
  return 0;
  }
}
]]>
</script>

五.示例分析

1.元素(标签)与属性

<person sex="female">
  <firstname>Anna</firstname>
  <lastname>Smith</lastname>
</person> 

<person>
  <sex>female</sex>
  <firstname>Anna</firstname>
  <lastname>Smith</lastname>
</person> 

在第一个例子中,sex 是一个属性。在第二个例子中,sex 则是一个子元素。两个例子均可提供相同的信息。

没有什么规矩可以告诉我们什么时候该使用属性,而什么时候该使用子元素。我的经验是在 HTML 中,属性用起来很便利,但是在 XML 中,您应该尽量避免使用属性。如果信息感觉起来很像数据,那么请使用子元素吧。

因使用属性而引起的一些问题:

  • 属性无法包含多重的值(元素可以)
  • 属性无法描述树结构(元素可以)
  • 属性不易扩展(为未来的变化)
  • 属性难以阅读和维护

请尽量使用元素来描述数据。而仅仅使用属性来提供与数据无关的信息。

2.C语言解析XML文件

使用C语言解析XML文件可以使用第三方库来完成,比如Expat和Libxml2等。

Expat是一款轻量级的、高速的XML解析器,它适用于嵌入式系统和移动设备等资源受限情况下的XML解析。使用Expat解析XML文件的基本步骤如下:

  1. 引入expat.h头文件。
  2. 创建一个XML解析器对象。
  3. 定义回调函数,用来处理XML元素和文本节点等信息。
  4. 调用XML解析器的解析函数,将XML文件以缓冲区方式传递给解析器。
  5. 处理完毕后释放解析器对象。

六.代码理解

1.源代码

#include <stdio.h>
#include <expat.h>

void start_element(void *data, const char *element, const char **attribute)
{
    printf("Start element: %s\n", element);
}

void end_element(void *data, const char *element)
{
    printf("End element: %s\n", element);
}

void handle_data(void *data, const char *content, int length)
{
    char buffer[100];
    strncpy(buffer, content, length);
    buffer[length] = '\0';
    printf("Data: %s\n", buffer);
}

int main()
{
    XML_Parser parser = XML_ParserCreate(NULL);
    XML_SetElementHandler(parser, start_element, end_element);
    XML_SetCharacterDataHandler(parser, handle_data);

    FILE *fp = fopen("example.xml", "r");
    char buf[1024];
    int len;
    while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
    {
        if (!XML_Parse(parser, buf, len, feof(fp)))
        {
            fprintf(stderr, "Parse error at line %d:\n%s\n",
                    XML_GetCurrentLineNumber(parser),
                    XML_ErrorString(XML_GetErrorCode(parser)));
            return 1;
        }
    }

    XML_ParserFree(parser);
    fclose(fp);

    return 0;
}

2.注释

以下是对每一行代码的解释:

#include <stdio.h>
#include <expat.h>

这两个语句分别引入了stdio.hexpat.h头文件,前者是标准输入输出库的头文件,后者是Expat XML解析器库的头文件。

void start_element(void *data, const char *element, const char **attribute)
{
    printf("Start element: %s\n", element);
}

定义一个回调函数start_element,用于处理XML元素开始标签。该函数接受三个参数:指向用户数据的指针、元素名称、属性数组。

void end_element(void *data, const char *element)
{
    printf("End element: %s\n", element);
}

定义一个回调函数end_element,用于处理XML元素结束标签。该函数接受两个参数:指向用户数据的指针、元素名称。

void handle_data(void *data, const char *content, int length)
{
    char buffer[100];
    strncpy(buffer, content, length);
    buffer[length] = '\0';
    printf("Data: %s\n", buffer);
}

定义一个回调函数handle_data,用于处理XML文本节点。该函数接受三个参数:指向用户数据的指针、文本内容、文本长度。

int main()
{
    XML_Parser parser = XML_ParserCreate(NULL);
    XML_SetElementHandler(parser, start_element, end_element);
    XML_SetCharacterDataHandler(parser, handle_data);

在主函数中,先创建了一个XML解析器对象parser,并通过XML_ParserCreate(NULL)函数创建。然后,分别使用XML_SetElementHandler()XML_SetCharacterDataHandler()函数设置回调函数,用于处理元素开始标签、元素结束标签和文本节点。

 FILE *fp = fopen("example.xml", "r");
    char buf[1024];
    int len;
    while ((len = fread(buf, 1, sizeof(buf), fp)) > 0)
    {
        if (!XML_Parse(parser, buf, len, feof(fp)))
        {
            fprintf(stderr, "Parse error at line %d:\n%s\n",
                    XML_GetCurrentLineNumber(parser),
                    XML_ErrorString(XML_GetErrorCode(parser)));
            return 1;
        }
    }

    XML_ParserFree(parser);
    fclose(fp);

    return 0;
}

接着打开XML文件,并使用fread()函数从文件中读取数据缓冲到buf数组中,然后调用XML_Parse()函数进行解析。如果解析出错,则输出错误信息。最后释放XML解析器对象,并关闭文件。

以上代码实现了Expat解析XML文件的基本流程,通过设置回调函数可以处理不同类型的XML节点。

注明:XML和html类似,了解html即可,作为传输数据的工具时,它又逐渐被JSON替代,所以我们只需要知道他不需要精通。

posted @   挽留岁月挽留你  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
  1. 1 原来你也在这里 周笔畅
  2. 2 世间美好与你环环相扣 柏松
  3. 3 起风了 吴青峰
  4. 4 极恶都市 夏日入侵企划
世间美好与你环环相扣 - 柏松
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 尹初七

作曲 : 柏松

编曲 : 彭圣杰

偏偏秉烛夜游

偏偏秉烛夜游

午夜星辰 似奔走之友

爱你每个结痂伤口

酿成的陈年烈酒

入喉尚算可口

入喉尚算可口

怎么泪水 还偶尔失守

邀你细看心中缺口

裂缝中留存 温柔

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

让樱花偷偷 吻你额头

让世间美好 与你环环相扣

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

当樱花开的纷纷扬扬

当世间美好 与你环环相扣

特别鸣谢:槿葵,我们的海报制作妹妹。

原唱:柏松

吉他:柏松

和声:柏松

录音:柏松

混音:张强

点击右上角即可分享
微信分享提示