鴻蒙HarmonyOS實戰-ArkTS語言基礎類庫(XML)

蜀道山QAQ發表於2024-06-06

🚀前言

資料傳輸的資料格式有以下幾種常見的格式:

  • JSON(JavaScript Object Notation):JSON是一種輕量級的資料交換格式,可讀性高且易於解析。它使用鍵值對的方式表示資料,並且支援多層巢狀。

  • XML(eXtensible Markup Language):XML是一種標記語言,可用於儲存和傳輸結構化資料。它使用標籤來定義資料和資料之間的關係。

  • Form Data(表單資料):表單資料是一種常見的資料傳輸格式,透過HTTP請求中的表單提交進行資料傳輸,資料以鍵值對的形式存在。

完整的XML相關知識點可以看這篇文章:https://blog.csdn.net/aa2528877987/article/details/122660175

本文主要講解HarmonyOS中XML生成、解析、轉換。

🚀一、XML

🔎1.概述

XML是可擴充套件標記語言(eXtensible Markup Language)的縮寫。它是一種用於表示和傳輸結構化資料的標記語言。XML使用自定義的標籤來標記資料的各個部分,並使用起始標籤和結束標籤將資料包裹起來。這種結構化的格式使得資料可以被解析和處理,從而更好地進行資料交換和儲存。

與HTML類似,XML也使用尖括號(< >)來定義標籤。但與HTML不同,XML標籤是自定義的,可以根據需要建立新的標籤。XML還支援屬性,可以在標籤中新增額外的資訊。XML資料可以透過解析器解析為可用的物件,如樹狀結構或文件物件模型(DOM),從而進行進一步的處理和操作。

XML被廣泛應用於資料儲存、資料交換和Web服務等領域。它是一種通用的、可擴充套件的標記語言,可以適應不同的資料結構和應用需求。

🔎2.組成

XML文件是由元素、屬性和內容組成的。以下是它們的詳細解釋:

  • 元素(element):XML文件的基本構建塊,也是文件的結構和資料的組織單元。元素由開始標籤和結束標籤組成,兩者之間包含了元素的內容。

例如:

<book>
  <title>XML for Beginners</title>
  <author>John Doe</author>
</book>
<book>、<title>和<author>都是元素。
  • 屬性(attribute):元素的附加資訊,以名稱-值對的形式出現在開始標籤中。屬性提供有關元素的額外資訊。

例如:

<book category="fiction">
  <title>XML for Beginners</title>
  <author>John Doe</author>
</book>

category是book元素的屬性,其值為fiction。

  • 內容(content):元素中的文字或其他元素。在元素的開始標籤和結束標籤之間可以包含文字或其他元素。

例如:

<book>
  <title>XML for Beginners</title>
  <author>John Doe</author>
</book>
<title>XML for Beginners</title>和<author>John Doe</author>是book元素的內容。

🔎3.文件結構定義形式

🦋3.1 XML Schema

在XML中使用XML Schema定義結構的方式是使用一個獨立的XML Schema檔案,該檔案定義了你希望XML文件符合的結構規範。

首先,建立一個XML Schema檔案,例如"example.xsd"。在該檔案中定義你的元素、屬性和資料型別。以下是一個示例XML Schema檔案的基本結構:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <!-- 在這裡定義你的元素、屬性和資料型別 -->
</xs:schema>

接下來,在你的XML文件中引用該XML Schema檔案,以使XML文件與定義的結構匹配。為此,在XML文件的根元素上新增一個xmlns:xsi屬性和xsi:schemaLocation屬性。xmlns:xsi屬性指定XML名稱空間xsi的定義,xsi:schemaLocation屬性指定XML Schema檔案的位置。

下面是一個示例XML文件的基本結構,引用了上述的XML Schema檔案:

<?xml version="1.0" encoding="UTF-8"?>
<rootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://www.example.com example.xsd">
    <!-- 在這裡編寫你的XML文件 -->
</rootElement>

xmlns:xsi屬性定義了xsi名稱空間,並指定了其定義的位置。xsi:schemaLocation屬性指定了XML Schema檔案的位置,其中"http://www.example.com"是XML名稱空間的URI,"example.xsd"是XML Schema檔案的位置。

該XML文件的結構和內容應符合在XML Schema檔案中定義的規範。如果XML文件與XML Schema不匹配,解析器將會報告錯誤。

🦋3.2 DTD

DTD(Document Type Definition)是一種用來定義XML文件結構的語言,它可以定義元素、屬性和實體的規則和約束。

<!DOCTYPE bookstore [
  <!ELEMENT bookstore (book+)>
  <!ELEMENT book (title, author, price)>
  <!ELEMENT title (#PCDATA)>
  <!ELEMENT author (#PCDATA)>
  <!ELEMENT price (#PCDATA)>

  <!ATTLIST book id ID #IMPLIED>
  <!ATTLIST book category CDATA #REQUIRED>
]>

<bookstore>
  <book category="Children">
    <title>Harry Potter</title>
    <author>J.K. Rowling</author>
    <price>29.99</price>
  </book>
  <book category="Fiction">
    <title>The Catcher in the Rye</title>
    <author>J.D. Salinger</author>
    <price>19.99</price>
  </book>
</bookstore>

透過<!DOCTYPE>宣告引用了DTD定義,然後使用<!ELEMENT>定義了元素的結構,<!ATTLIST>定義了元素的屬性。

  • 定義了bookstore元素必須包含一個或多個book元素。
  • 定義了book元素包含title、author和price三個子元素。
  • 定義了title元素只能包含文字內容。
  • 定義了author元素只能包含文字內容。
  • 定義了price元素只能包含文字內容。
  • 定義了book元素有一個可選的id屬性,型別為ID。
  • 定義了book元素必須有一個category屬性,型別為CDATA。

🔎4.生成

import xml from '@ohos.xml';
import util from '@ohos.util';
// 1.基於Arraybuffer構造XmlSerializer物件
// @ts-ignore
let arrayBuffer = new ArrayBuffer(2048); // 建立一個2048位元組的緩衝區
// @ts-ignore
let thatSer = new xml.XmlSerializer(arrayBuffer); // 基於Arraybuffer構造XmlSerializer物件

// 2.基於DataView構造XmlSerializer物件
// @ts-ignore
let arrayBuffer = new ArrayBuffer(2048); // 建立一個2048位元組的緩衝區
let dataView = new DataView(arrayBuffer); // 使用DataView物件操作ArrayBuffer物件
// @ts-ignore
let thatSer = new xml.XmlSerializer(dataView); // 基於DataView構造XmlSerializer物件
thatSer.setDeclaration(); // 寫入xml的宣告
thatSer.startElement('bookstore'); // 寫入元素開始標記
thatSer.startElement('book'); // 巢狀元素開始標記
thatSer.setAttributes('category', 'COOKING'); // 寫入屬性及屬性值
thatSer.startElement('title');
thatSer.setAttributes('lang', 'en');
thatSer.setText('Everyday'); // 寫入標籤值
thatSer.endElement(); // 寫入結束標記
thatSer.startElement('author');
thatSer.setText('Giada');
thatSer.endElement();
thatSer.startElement('year');
thatSer.setText('2005');
thatSer.endElement();
thatSer.endElement();
thatSer.endElement();

let view = new Uint8Array(arrayBuffer); // 使用Uint8Array讀取arrayBuffer的資料
let textDecoder = util.TextDecoder.create(); // 呼叫util模組的TextDecoder類
let res = textDecoder.decodeWithStream(view); // 對view解碼
console.info(res);

得到結果

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<bookstore>\r\n  
    <book category=\"COOKING\">\r\n    
        <title lang=\"en\">Everyday</title>\r\n    
        <author>Giada</author>\r\n    
        <year>2005</year>\r\n  
    </book>\r\n
</bookstore>

🔎5.解析

🦋5.1 解析XML標籤和標籤值

import xml from '@ohos.xml';
import util from '@ohos.util'; // 需要使用util模組函式對檔案編碼
let strXml =
  '<?xml version="1.0" encoding="utf-8"?>' +
  '<note importance="high" logged="true">' +
  '<title>Play</title>' +
  '<lens>Work</lens>' +
  '</note>';
let textEncoder = new util.TextEncoder();
let arrBuffer = textEncoder.encodeInto(strXml); // 對資料編碼,防止包含中文字元亂碼
// 1.基於ArrayBuffer構造XmlPullParser物件
let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');

// // 2.基於DataView構造XmlPullParser物件
// let dataView = new DataView(arrBuffer.buffer);
// let that = new xml.XmlPullParser(dataView, 'UTF-8');

let str = '';
function func(name, value){
  str = name + value;
  console.info(str);
  return true; //true:繼續解析 false:停止解析
}
let options = {supportDoctype:true, ignoreNameSpace:true, tagValueCallbackFunction:func};
that.parse(options);

得到結果

note
title
Play
title
lens
Work
lens
note

image

🦋5.2 解析XML屬性和屬性值

import xml from '@ohos.xml';
import util from '@ohos.util'; // 需要使用util模組函式對檔案編碼
let strXml =
  '<?xml version="1.0" encoding="utf-8"?>' +
  '<note importance="high" logged="true">' +
  '    <title>Play</title>' +
  '    <title>Happy</title>' +
  '    <lens>Work</lens>' +
  '</note>';
let textEncoder = new util.TextEncoder();
let arrBuffer = textEncoder.encodeInto(strXml); // 對資料編碼,防止包含中文字元亂碼
let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');
let str = '';
function func(name, value){
  str += name + ' ' + value + ' ';
  return true; // true:繼續解析 false:停止解析
}
let options = {supportDoctype:true, ignoreNameSpace:true, attributeValueCallbackFunction:func};
that.parse(options);
console.info(str); // 一次列印出所有的屬性及其值

image

🦋5.3 解析XML事件型別和元素深度

import xml from '@ohos.xml';
import util from '@ohos.util'; // 需要使用util模組函式對檔案編碼
let strXml =
  '<?xml version="1.0" encoding="utf-8"?>' +
  '<note importance="high" logged="true">' +
  '<title>Play</title>' +
  '</note>';
let textEncoder = new util.TextEncoder();
let arrBuffer = textEncoder.encodeInto(strXml); // 對資料編碼,防止包含中文字元亂碼
let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');
let str = '';
function func(name, value){
  str = name + ' ' + value.getDepth(); // getDepth 獲取元素的當前深度
  console.info(str)
  return true; //true:繼續解析 false:停止解析
}
let options = {supportDoctype:true, ignoreNameSpace:true, tokenValueCallbackFunction:func};
that.parse(options);
console.info(str); // 一次列印出所有的屬性及其值

得到結果

0 0 // 0:<?xml version="1.0" encoding="utf-8"?> 對應事件型別START_DOCUMENT值為0  0:起始深度為0
2 1 // 2:<note importance="high" logged="true"> 對應事件型別START_TAG值為2       1:深度為1
2 2 // 2:<title>對應事件型別START_TAG值為2                                       2:深度為2
4 2 // 4:Play對應事件型別TEXT值為4                                               2:深度為2
3 2 // 3:</title>對應事件型別END_TAG值為3                                        2:深度為2
3 1 // 3:</note>對應事件型別END_TAG值為3                                         1:深度為1(與<note對應>)
1 0 // 1:對應事件型別END_DOCUMENT值為1                                           0:深度為0

image

🦋5.4 場景示例

import xml from '@ohos.xml';
import util from '@ohos.util';

let strXml =
  '<?xml version="1.0" encoding="UTF-8"?>' +
    '<book category="COOKING">' +
    '<title lang="en">Everyday</title>' +
    '<author>Giada</author>' +
    '</book>';
let textEncoder = new util.TextEncoder();
let arrBuffer = textEncoder.encodeInto(strXml);
let that = new xml.XmlPullParser(arrBuffer.buffer, 'UTF-8');
let str = '';

function tagFunc(name, value) {
  str = name + value;
  console.info('tag-' + str);
  return true;
}

function attFunc(name, value) {
  str = name + ' ' + value;
  console.info('attri-' + str);
  return true;
}

function tokenFunc(name, value) {
  str = name + ' ' + value.getDepth();
  console.info('token-' + str);
  return true;
}

let options = {
  supportDocType: true,
  ignoreNameSpace: true,
  tagValueCallbackFunction: tagFunc,
  attributeValueCallbackFunction: attFunc,
  tokenValueCallbackFunction: tokenFunc
};
that.parse(options);

得到結果

tag-
token-0 0
tag-book
attri-category COOKING
token-2 1
tag-title
attri-lang en
token-2 2
tag-Everyday
token-4 2
tag-title
token-3 2
tag-author
token-2 2
tag-Giada
token-4 2
tag-author
token-3 2
tag-book
token-3 1
tag-
token-1 0

image

🔎6.轉換

import convertxml from '@ohos.convertxml';
let xml =
  '<?xml version="1.0" encoding="utf-8"?>' +
  '<note importance="high" logged="true">' +
  '    <title>Happy</title>' +
  '    <todo>Work</todo>' +
  '    <todo>Play</todo>' +
  '</note>';
let options = {
  // trim: false 轉換後是否刪除文字前後的空格,否
  // declarationKey: "_declaration" 轉換後檔案宣告使用_declaration來標識
  // instructionKey: "_instruction" 轉換後指令使用_instruction標識
  // attributesKey: "_attributes" 轉換後屬性使用_attributes標識
  // textKey: "_text" 轉換後標籤值使用_text標識
  // cdataKey: "_cdata" 轉換後未解析資料使用_cdata標識
  // docTypeKey: "_doctype" 轉換後文件型別使用_doctype標識
  // commentKey: "_comment" 轉換後註釋使用_comment標識
  // parentKey: "_parent" 轉換後父類使用_parent標識
  // typeKey: "_type" 轉換後元素型別使用_type標識
  // nameKey: "_name" 轉換後標籤名稱使用_name標識
  // elementsKey: "_elements" 轉換後元素使用_elements標識
  trim: false, declarationKey: "_declaration",
  instructionKey: "_instruction", attributesKey: "_attributes",
  textKey: "_text", cdataKey: "_cdata", doctypeKey: "_doctype",
  commentKey: "_comment", parentKey: "_parent", typeKey: "_type",
  nameKey: "_name", elementsKey: "_elements"
}
let conv = new convertxml.ConvertXML();
let result = conv.convertToJSObject(xml, options);
let strRes = JSON.stringify(result); // 將js物件轉換為json字串,用於顯式輸出
console.info(strRes);
// 也可以直接處理轉換後的JS物件,獲取標籤值
let title = result['_elements'][0]['_elements'][0]['_elements'][0]['_text']; // 解析<title>標籤對應的值
let todo = result['_elements'][0]['_elements'][1]['_elements'][0]['_text']; // 解析<todo>標籤對應的值
let todo2 = result['_elements'][0]['_elements'][2]['_elements'][0]['_text']; // 解析<todo>標籤對應的值
console.info(title); // Happy
console.info(todo); // Work
console.info(todo2); // Play

image

🚀寫在最後

  • 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  • 關注小編,同時可以期待後續文章ing🚀,不定期分享原創知識。
  • 更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

image

相關文章