varch/doc/xml.md
2024-07-21 19:02:13 +08:00

7.4 KiB
Raw Permalink Blame History

介绍

C语言xml解释器。包含xml文本文件解析和生成适合大部分的C语言平台。

使用例子

生成

测试代码

void test_write(void)
{
    xml_t root, x;

    root = xml_create("root");
    if (!root) return;

    x = xml_create("name");
    xml_set_text(x, "xml parser");
    xml_insert(root, 0, x);

    x = xml_create("description");
    xml_set_text(x, "This is a C language version of xml parser.");
    xml_insert(root, 1, x);

    x = xml_create("license"); 
    xml_set_text(x, "GPL3.0");
    xml_insert(root, 2, x);
    
    xml_file_dump(root, "write.xml");

    xml_delete(root);
}

生成文件名: write.xml

<root>
	<name>xml parser</name>
	<description>This is a C language version of xml parser.</description>
	<license>GPL3.0</license>
</root>

解析

文件名: read.xml

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
	<book category="CHILDREN">
		<title>Harry Potter</title>
		<author>J K.Rowling</author>
		<year>2005</year>
		<price>29.99</price>
	</book>
	<book category="WEB">
		<title>Learning XML</title>
		<author>Erik T.Ray</author>
		<year>2004</year>
		<price>39.95</price>
	</book>
</bookstore>

测试代码

void test_read(void)
{
    xml_t root, x;
    
    root = xml_file_load(READ_FILE);
    if (!root) return;

    printf("load success!\r\n");

    x = xml_to(root, "book", 1);
    printf("x attr: %s\r\n", xml_get_attribute(x, NULL, 0));

    x = xml_to(x, "author", 0);
    printf("author: %s\r\n", xml_get_text(x));

    xml_delete(root);
}

打印结果

load success!
x attr: WEB
author: Erik T.Ray

xml语法

xml文档必须有根元素

xml必须包含根元素它是所有其他元素的父元素比如以下实例中 root 就是根元素:

<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>

XML声明

XML 声明文件的可选部分,如果存在需要放在文档的第一行,如下所示:

<?xml version="1.0" encoding="utf-8"?>
  • 该xml只是支持这个声明的解析没实际应用解析版本和编码

所有的 XML 元素都必须有一个关闭标签

在 XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签:

<p>This is a paragraph.</p>

XML 标签对大小写敏感

XML 标签对大小写敏感。标签 与标签 是不同的。
必须使用相同的大小写来编写打开标签和关闭标签:

<Message>这是错误的</message>
<message>这是正确的</message>

XML 必须正确嵌套

在 XML 中,所有元素都必须彼此正确地嵌套:

<b><i>This text is bold and italic</i></b>

XML 属性值必须加引号

在 XML 中XML 的属性值必须加引号。

<note date=12/11/2007>
<to>Tove</to>
<from>Jani</from>
</note>
<note date="12/11/2007">
<to>Tove</to>
<from>Jani</from>
</note>

在第一个文档中的错误是note 元素中的 date 属性没有加引号。

实体引用

在 XML 中,一些字符拥有特殊的意义。
如果您把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。
这样会产生 XML 错误:

<message>if salary < 1000 then</message>

为了避免这个错误,请用实体引用来代替 "<" 字符:

<message>if salary &lt; 1000 then</message>

在 XML 中,有 5 个预定义的实体引用:

&lt; < less than
&gt; > greater than
&amp; & ampersand
&apos; ' apostrophe
&quot; " quotation mark

注释:在 XML 中,只有字符 "<" 和 "&" 确实是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。

操作方法

常用方法

xml解析

方法原型

xml_t xml_loads(const char* text);
xml_t xml_file_load(const char* filename);

xml_loads函数传进xml文本信息则可以返回解析出来的xml对象句柄。 xml_file_load函数则是直接传入文件名即可加载文件返回xml对象函数内部通过C语言标准文件操作函数集对文件进行读取然后套用xml_loads函数进行解析支持utf8编码文件。

xml生成

方法原型

char* xml_dumps(xml_t xml, int preset, int unformat, int* len);
int xml_file_dump(xml_t xml, char* filename);

xml_dumps函数将xml对象转换成文本信息其中preset为预置的文本长度,预置的长度和最终输出文本长度接近则可以减小内存重分配的次数而提高转换效率;unformat是否不采用格式化输出,不采用格式化则文本会挤在一行;len是转换的输出长度。
xml_file_dump函数套用了xml_dumps函数将文本信息存储到指定名字的文件。

xml创建对象和删除对象

方法原型

xml_t xml_create(void);
void xml_delete(xml_t xml);

xml_create创建返回一个空xml对象返回NULL即失败。xml_delete则是删除xml对象。

xml获取子对象

方法原型

xml_t xml_to(xml_t xml, const char *name, int index);

在xml对象中name是不查重的也就是在同一个层级的xml中可能存在多个同名的namexml_to方法则是可以用于匹配特定的name。此函数name传入NULL时则只有index起作用按照索引来匹配子对象name不为NULL的时候则只会匹配相应key的子对象并通过index来指示匹配第几个名为name的对象。

t = xml_to(xml, NULL, 3); // 找索引为3的子对象
t = xml_to(xml, "a", 3); // 找键为"a"索引为3的子对象

xml设置和获取文本

方法原型

int xml_set_text(xml_t xml, const char *text);
const char* xml_get_text(xml_t xml);

这两个方法分别设置xml的文本和获取xml文本。

xml添加和移除属性

方法原型

int xml_add_attribute(xml_t xml, const char *name, const char *value);
int xml_remove_attribute(xml_t xml, const char *name, int index);

xml_add_attribute会在xml的首位置添加一个name对应value的属性。
xml_remove_attribute则类似xml_to的匹配逻辑,移除特定的属性。
这两个方法操作成功返回1失败返回0。

xml获取属性

const char* xml_get_attribute(xml_t xml, const char *name, int index);

类似xml_to的匹配逻辑获取相应的属性值。

xml插入和删除子对象

方法原型

int xml_insert(xml_t xml, int index, xml_t ins);
int xml_remove(xml_t xml, const char *name, int index);

xml_insert方法是将创建后的对象按照索引插入到另一个对象中。
xml_remove方法和xml_remove_attribute类似移除特定的子对象。
这两个方法操作成功返回1失败返回0。

xml解析报错

错误类型包含以下几种

#define XML_E_OK				0 // ok
#define XML_E_TEXT				1 // empty text
#define XML_E_MEMORY			2 // memory
#define XML_E_LABEL				3 // label
#define XML_E_VERSION			4 // version
#define XML_E_ENCODING			5 // encoding
#define XML_E_ILLEGAL			6 // illegal character
#define XML_E_END				7 // end
#define XML_E_VALUE				8 // missing value
#define XML_E_QUOTE				9 // missing quete
#define XML_E_COMMENT			10 // missing comment tail -->
#define XML_E_NOTES				11 // head notes error
#define XML_E_CDATA			    12 // missing comment tail ]]>