编辑
Qt源码在后面,文本介绍Qt国际化语言和XML
XML基础(一)
## 1、概述
### 1.1 定义(xml是个啥玩意儿?)
XML(extensible Markup Language)俗称差妹儿,专业称之为:可拓展标记语言。
- (1)何为标记,指的是一种标记语言,或者标签语言,即用一系列的标签来对数据进行描述。
- (2)何为拓展,简单来说就是用户可以自己定义标签。
### 1.2 作用(能用来干啥?)
- (1)作为数据传输的标准。好读,好维护,好扩展,与编程语言无关,任谁都会选择他来担任这个数据传输的角色吧。。。
- (2)作为配置文件。其实很多软件和框架,都会提供XML文件配置的方式,以便可以方便快捷的修改软件或框架的功能。
- (3)持久化数据。啥意思?简单来说就是可以将数据存到xml文件中,把xml当做一个临时的小型数据库。当然,重要的数据还是要存到正经的数据库中的,别问为什么,问就是xml存数据会不安全(doge)。
- (4)简化平台变更。在系统更换平台的时候,普通的数据会存在不兼容的问题,但是XML 数据以文本格式存储,使得 XML 在不损失数据的情况下,更容易扩展和升级。简直不要太好用。
### 1.3 历史(简单讲讲XML的故事?)
最开始的标记语言是GML(通用标记语言),1969年出生的,就是用来做计算机之间的通信,通信就会传输数据。后面GML发现自己不是很好,就开始自省,完善自身,于是在1985年重获新生,改名为SGML(标准通用标记语言),也是用来通信,传输数据。随着万维网的不断发展,1993年,在SGML基础上有出现了HTML语言( HTML 超文本的标记语言(HyperText Markup Language)),这个名字应该很是耳熟吧,前端必学呀,主要是用于万维网上的页面展示。但HEML仍有不少缺陷,于是这篇博客的主角诞生了,1998年,W3C组织推出了XML(可扩展标记语言),本来是想用XML代替HTML的,但没想到事与愿违,他们之间还是有一定差别,即便现在,XML也没能完成主子给它的任务,因为HTML在整个万维网的使用太广泛了(人家早出身几年,经历的也多,人缘广泛,想强行替代别人还是有点脱离现实了)
XML和HTML对比
- 1、XML主要用来描述数据
- 2、HTML主要用来显示数据
## 2、XML语法
### 2.1 文档声明
XML声明文件的可选部分,如果存在,则需要放在文档的第一行。如下
<?xml version="1.0" encoding="utf-8"?>
这里描述了xml的版本以及文档所用的编码格式
### 2.2 元素
定义
元素指的就是XML中的标记,这种标记也被称为标签、节点(节点这种称呼常见于框架中)
书写规范
一个XML元素可以包含字母、数字以及其它一些可见字符,但必须遵守下面的一些规范:
- 不能以数字或部分标点符号开头
- 不能包含空格和特定的几个符号
- 标签必须成对出现不允许缺省结束标签
- 根元素有且只有一个,它是所有其他元素的父元素
- 大小写敏感
- 允许多层嵌套但是不允许交叉嵌套
<root> <child> <subchild>...</subchild> </child></root>// 这里的标签就是根元素,如上
<root> <a>www.baidu.com</a></root>// 元素是可以包含标签体的,如上
<root> <a></a><root>// 元素也可以不包含标签体,如上
<root> <a> www.baidu.com </a></root><root> <a>www.baidu.com</a></root>// 对于XML标签中出现的空格和换行,在XML解析程序都会当作标签内容进行处理,如上面两个代码,标签中内容还是有区别的,如上
### 2.3 属性
定义
属性(Attribute)提供了元素相关的一些额外信息。
使用规范
XML 属性写在开始标签中,并且属性值必须加引号,例如,可以是双引用,也可以是单引号,如下
<root> <person sex="female"></person></root>
一个元素可以有多个属性,它的基本格式为:<元素名 属性名=“属性值” 属性名=“属性值”>
<root> <person sex="female" age='18' email="xxqq.com"></person></root>
元素和属性使用实例
如果有多个相同标签的时候,可以使用 id进行区别
<message> <note id="1"> <date> <day>10</day> <month>02</day> <year>2021</year> </date> <to>tom</to> <from>mary</from> <msg>love</msg> </note> <note id="2"> <date> <day>10</day> <month>02</day> <year>2021</year> </date> <to>tom</to> <from>mary</from> <msg>together</msg> </note></message>
### 2.4 实体
定义
一些字符拥有特殊的意义,在XML文档中,是不能直接使用的。
如果把字符 “<” 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。
<?xml version="1.0" encoding="utf-8"?><message>if salary < 1000 then</message>
此时浏览器会报错:invalid element name
这时候,可以使用XML中预定义的实体,来代替这个特殊符号,如下
<?xml version="1.0" encoding="utf-8"?><message>if salary < 1000 then</message>
预定义实体与自定义实体
预定义实体
XML中预定义实体有[你会看到Qt中的.ui文件就是XML格式的文件]
实体 | 字符 | 简介 |
& lt; | < | Less than |
& gt; | Greater than | |
& | & | mpersand |
& apos; | ' | Apostrophe |
& quot; | " | Quotation mark |
可以看到定义实体的格式:&实体名
自定义实体
格式:
<!DOCTYPE 根元素名称[ <!ENTITY 实体名 实体内容>]>
例如:
<!DOCTYPE root[ <!ENTITY school "清华大学">]><root> <name>&school;</name></roo>
浏览器显示结果如下:
编辑
### 2.5 注释
格式:
<!-- 注释内容 -->
- 1
使用注释时注意一下几点
(1)注释内容中不要出现–
<!-- -- -->
<!-- 上面的注释会报错 -->
- 1
- 2
- 3
(2)不要把注释放在标签中间
(3)注释不能嵌套
## 3、CDATA
XML 解析器,会解析 XML 文档中所有的文本。当某个 XML 元素被解析时,其标签之间的文本也会被解析。
<root> <tag> <name>&</name> <entity>&</entity> </tag></root>
浏览器解析结果
编辑
在xml中
- 解析器进行解析的内容,称为PCDATA(Parsed CDATA)
- 解析器不会解析的内容,称为CDATA,(Character Data)
在一些情况下,我们在xml中编写的特殊内容,例如特殊字符、代码等,并不希望解析器去解析,而是希望把这些内容按字符串原样输出即可,不需要做额外任何解析处理。这时候,我们就可以把这些内容,写在指定的CDATA区域内即可。
CDATA区域的格式
例如:
<root> <tag> <name>&</name> <entity><![CDATA[&]]></entity> </tag></root>// 输出&
- XML 文档中的所有文本均会被解析器解析。只有 CDATA 区段中的文本会被解析器
## 4、XML和CSS
CSS简介
XML文件中的内容,可以配合CSS进行内容的样式渲染,例如控制字体大小、颜色等。
CSS(Cascading Style Sheets) 层叠样式表,通常用来给HTML中内容、或者XML中内容进行样式的渲染
例如:先创建一个css后缀的文件,在该文件中编写下面的代码
name{ font-size:30px; font-weight:bold; color:red;}name{ font-size:30px; font-weight:bold; color:green;}
处理指令
处理指令,简称PI (processing instruction),可以用来指定解析器如何解析XML文档内容。
例如:在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,使用test.css文件来渲染xml内容。
<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href="test.css" type="text/css"?> <class> <student id="001"> <name>张三</name> <age>20</age> </student> <student id="002"> <name>李四</name> <age>20</age> </student></class>
渲染后的效果如下:
编辑
## 5、Qt XML
XML和Qt密不可分,还记得QT的.ui文件吗,就是XML文件 |
未来XML的用户使用量只增不减,所以有必要记录一下。
## 5.1 .pro文件
采用的是命令行项目,没有.ui文件的
# 配置命令行cmdlineCONFIG += cmdlineQT -= guiSOURCES += main.cpp# 【1】 如果项目很大 需要添加resources_bigCONFIG += resources_big# 【2】国际化语言翻译文件绝对路径TRANSLATIONS += translation/tr_zh.ts \ translation/tr_en.ts# installtarget.path = $$[QT_INSTALL_EXAMPLES]/xml/xmlstreamlintINSTALLS += target
【2】是生成国际化语言的绝对路径,还需执行以下操作才能生成完整的多国翻译文件。
更新翻译:生成.ts文件
编辑
发布翻译:生成.qm文件
编辑
如果你想翻译多个国家的语言,就在对应的.ts文件修改即可
编辑
<translation type="unfinished">填写你翻译的文本</translation>
Qt国际化语言相对简单,但不是本节的重点,只是代码中有使用tr()函数,所以让大家了解一下。 |
## 5.2 main文件
文本项目内容不多,所以直接在main全部实现,主要是对XML文件进行读写。【从myxml.xml文件读取->写入savaXML.xml文件】
/******************************************************************************** WX公众号:Qt历险记** CSDN博客网:Qt魔术师******************************************************************************/#include <QCoreApplication>#include <QFile>#include <QStringList>#include <QTextStream>#include <QXmlStreamReader>/* 此类的唯一目的是创建翻译上下文。【可以翻译成各个国家】*/class XmlStreamLint{public: // 从字面意思:声明tr函数 tr()函数就是用来处理国际化语言的 因为tr()时QObject的方法QObject::tr() or QObject::trUtf8(),而增加头文件会增加编译的时间 // 这个宏的功能:XmlStreamLint可以调用以下两个函数 /* static inline QString tr(const char *sourceText, const char *comment = 0); static inline QString trUtf8(const char *sourceText, const char *comment = 0); */ Q_DECLARE_TR_FUNCTIONS(XmlStreamLint) // 必须出现在类定义的最顶部};int main(int argc, char *argv[]){ enum ExitCode { Success, ParseFailure, ArgumentError, WriteError, FileFailure }; // 打包发布时可以设置插件的目录 默认路径列表由一个条目组成,即插件的安装目录。 // 由于Qt在构造QApplication时会加载插件,因此设置此项的机会就是在调用QApplication的构造函数之前进行 QCoreApplication::addLibraryPath("pluins"); QCoreApplication app(argc, argv); QTextStream errorStream(stderr); // 标准IO出错 errorStream <<"argc = "<<argc<<Qt::endl; errorStream <<"arg0 = "<<QCoreApplication::arguments().at(0) <<Qt::endl<<"arg1 = "<<QCoreApplication::arguments().at(1)<<Qt::endl <<Qt::endl<<"arg2 = "<<QCoreApplication::arguments().at(2)<<Qt::endl; // 外部参数 // 命令行参数个数可以在编译时指定:点击最左侧项目->点击Run按钮->在运行的下面第二行:mmand linearguments:行编辑框输入参数,参数之间空格分隔,注意一个完整的参数中不能有空格不然被分成了两个参数 if (argc != 3) { errorStream << XmlStreamLint::tr( "Usage: xmlstreamlint <path to XML file>\n"); return ArgumentError; } // 参数arg0是默认应用程序编译生成的.exe文件的绝对路径,arg1才是我们输入的第一个命令行参数 QString inputFilePath(QCoreApplication::arguments().at(1)); QFile inputFile(inputFilePath); // 文件不存在 if (!QFile::exists(inputFilePath)) { errorStream << XmlStreamLint::tr( "File %1 does not exist.\n").arg(inputFilePath); return FileFailure; } // 文件打开失败 else if (!inputFile.open(QIODevice::ReadOnly)) { errorStream << XmlStreamLint::tr( "Failed to open file %1.\n").arg(inputFilePath); return FileFailure; } // 写入我指定的另一个空的XML文件 QString outFilePath(QCoreApplication::arguments().at(2)); QFile outputFile(outFilePath); if (!outputFile.open(QIODevice::WriteOnly)) { errorStream << XmlStreamLint::tr("Failed to open " + outputFile.fileName().toUtf8()); return WriteError; }//! [第一步]//! // qxml流阅读器类提供了一个快速解析器,可以通过简单的流api读取格式良好的xml QXmlStreamReader reader(&inputFile); // qxml流媒体写入器类提供了一个具有简单流媒体api的xml写入器 QXmlStreamWriter writer(&outputFile);//! [end]//! [第二步] 按行读取XML文件 while (!reader.atEnd()) { reader.readNext(); if (reader.error()) // 解析错误 只是在那行那列 { errorStream << XmlStreamLint::tr( "Error: %1 in file %2 at line %3, column %4.\n").arg( reader.errorString(), inputFilePath, QString::number(reader.lineNumber()), QString::number(reader.columnNumber())); return ParseFailure;//! [end]//! [第三步] } else { // 写入读者的当前状态。支持所有可能的有效状态。此函数的目的是支持对xml数据的链式处理。 writer.writeCurrentToken(reader); // 读取的内容写入到文件中 } }//! [end] return Success;}
## 5.3 运行步骤
需要先添加命令行参数,才能有效果哦,注意命令行参数之间使用空格分隔,也就是你的路径中最好不要有空格,不然就被理解成多个参数了。
点击:
编辑
编辑
文件如下:如何快速添加路径
方法1:右键属性,安全,对象名称就是绝对路径
编辑
编辑
方法2是对方法1的拓展:在Exporer中显示,其他操作如同方法1
编辑
命令行添加完毕,可以运行
编辑
运行成功
编辑
使用VScode打开两个文件看看:
编辑
==XML远远不止这些,下次继续肝==
==END==