# string.xml 库模块帮助文档

<details>  <summary>使用说明</summary>  <p>

## string.xml 简介

string.html 则基于 string.xml 可用于解析 HTML 。

string.xml 的原则是实现宽松与简化的解析器。
对于 XML,HTML 中的笔误等努力尝试修正为正确的结构(例如属性值为空或没放在引号中,标记忘记关闭,
忘记写开始标识不配对,或大小写首尾不匹配 - 关于大小写会首先尝试严格配对,配对不成功会检测是否笔误并进行修正 ) 

注意此支持库的作用是简单解析,校验 XML 错误等不是此支持库的目标,
所以只会尽可能的解析出能解析的结果,尽可能宽容错误写法并试图自动修正。
如果需要比较严谨的XML解析器 - 请使用标准库中的 web.msxml 

string.xml 不会将属性值中的回车换行规范化为空格。

## 关于 XML 节点对象 

string.xml 解析 XML 文档后会返回一个表对象。
在这个表对象里所有的 XML 节点都是表对象。

这些 XML 节点对象可能具有 3 类元素：
节点对象可能具有 3 类元素：
1. 节点的属性存储为名值对成员，键值都是字符串。 
2. 所有相同标签名的子节点也存储为名值对成员，键为标签名，值为子节点数组。
3. 节点对象的数组成员存储了全部子节点。 

XML 节点对象分为 4 类：

1. 拥有标签名（ tagName 属性）的普通 XML 元素 
2. string.xml 总是虚拟出一个空的没有 tagName 属性的顶层根节点。 
3. 文本节点：使用 text 属性表示文本,无 tagName 属性,无其他属性。
4. CDATA节点：使用 cdata 属性表示数据, 无 tagName 属性,无其他属性

注意：

- XML 节点对象的 tagName 属性是用于表示 XML 标签名的保留属性，XML 定义的 tagName 属性将被忽略。
- XML 节点对象的 localTagName 属于是用于表示去掉命名空间前缀的保留属性，XML 定义的 localTagName 属性将被忽略。 
- string.xml 在解析 XML 时自动忽略所有注释，不会将注释存为节点对象。
- 将 XML 节点对象用于 tostring 函数或连接操作符时会自动调用 outerXml 方法转换为字符串。

## 如何正确遍历 XML 子节点 

下面这样会遍历 XML 节点对象的全部属性（名值对成员）与子节点（数组成员）

```aardio
for(k,v in parentNode){

}
```

下面这样仅遍历数组成员（也就是子节点数组）

```aardio
for(i=1;#parentNode;1){
	var node = parentNode[i]

}
```

也可以使用节点的 eachChild 方法创建迭代器以遍历全部子节点

```aardio
for(i,localTagName,childCount,xNode in parentNode.eachChild(tagName) ){
	/*
	参数中的 tagName 是可选的，忽略大小写且忽略目标节点的命名空间前缀。

	迭代变量：
	- i 为索引，
	- localTagName 为标签名（去掉命名空间前缀），
	- childCount 为当前子节点包含的子节点数目，
	- xNode 为当前子节点
	*/
}
```	

//查找第一个节点，参数 tagName 忽略大小写且忽略目标节点的命名空间前缀。
var first = parentNode.eachChild(tagName)

注意如果 eachChild 与 eachChild 方法的 tagName 参数本身指定命名空间前缀则不会被忽略。

遍历相同标签名的子节点：

```aardio
for(i,node in parentNode[tagName]){
	//parentNode[tagName] 只包含数组成员，可以用 for in 直接遍历

}
```

</p></details>

## string 成员列表 <a id="string" href="#string">&#x23;</a>

### string.xml() <a id="string.xml" href="#string.xml">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### string.xml(xmlText,elementTypes,optionalTags,inlineElements,preserveSpace) <a id="string.xml" href="#string.xml">&#x23;</a>
参数 @xmlText 指定 XML 文本。  
其他参数仅预留用于 string.html，一般不需要指定。

## string.xml 成员列表 <a id="string.xml" href="#string.xml">&#x23;</a>

简单 XML 解析器。  
严格的校验 XML 语法正确性不是本模块的设计目标，  
所以此解析器尽可能兼容错误，兼容了 HTML，SGML 的部分规则:  

1. 不要求存在根标签   
2. 尝试自动修正不配对的标记   
3. 在有必要的时候尝试忽略大小写。

创建 XML 对象。  
此对象不支持 table.tostring , console.dump 函数，不能跨线程传递。  

严格校验 XML 语法正确性不是本模块的义务和目标,  
所以,此解析器尽可能兼容错误,兼容了 HTML,SGML 的部分规则:  
1、不要求存在根标签   
2、尝试自动修正不配对的标记   
3、在有必要的时候尝试忽略大小写

### string.xml.escape() <a id="string.xml.escape" href="#string.xml.escape">&#x23;</a>
将字符串中的 < > " ' & 等 XML 标记字符编码为实体字符（entity）。  
如果参数为非 null 值则返回转换后的字符串。  
参数只能是 null 或字符串、buffer

### string.xml.escape2(str,pattern) <a id="string.xml.escape2" href="#string.xml.escape2">&#x23;</a>
将字符串参数 @str 中以 @pattern 指定模式串所匹配的字符进行 NCR 编码。  
参数 @pattern 可用模式匹配语法指定要编码的字符，省略则默认为 `:|[\<\>\&"']`，也就是仅编码非 ACSII 字符与 `<>&"'` 这 5 个基本实体字符。  

返回编码后的字符串。

### string.xml.unescape() <a id="string.xml.unescape" href="#string.xml.unescape">&#x23;</a>
NCR 编码字符、HTML 实体字符还原为 UTF8 文本。  
此函数默认只会解码  XML 基本命名实体与常用 HTML 命名实体字符。  
如果提前导入 web.entities 库则支持解码全部 HTML 命名实体（实体必须以 `;` 号结尾）。

## stringXmlObject 成员列表 <a id="stringXmlObject" href="#stringXmlObject">&#x23;</a>

### stringXmlObject.* <a id="stringXmlObject.any" href="#stringXmlObject.any">&#x23;</a>
属性或子节点数组  

[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.codepage <a id="stringXmlObject.codepage" href="#stringXmlObject.codepage">&#x23;</a>
源文本代码页

### stringXmlObject.declaration <a id="stringXmlObject.declaration" href="#stringXmlObject.declaration">&#x23;</a>
DOCTYPE 声明拥有此属性

### stringXmlObject.eachAttribute() <a id="stringXmlObject.eachAttribute" href="#stringXmlObject.eachAttribute">&#x23;</a>

```aardio
for( k,v in stringXmlObject.eachAttribute() ){
	/*遍历节点所有属性,k 为属性名,v 为属性值*/
}
```

### stringXmlObject.eachChild() <a id="stringXmlObject.eachChild" href="#stringXmlObject.eachChild">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.eachChild(tagName) <a id="stringXmlObject.eachChild" href="#stringXmlObject.eachChild">&#x23;</a>

```aardio
for(i,localTagName,childCount,xNode in stringXmlObject.eachChild() ){  
	/*  
	可选参数 @tagName 指定子元素标签名（忽略大小写，忽略目标节点命名空间前缀）。  

	迭代变量：  
	- i 为索引，  
	- localTagName 为标签名（去掉命名空间前缀），  
	- childCount 为当前子节点包含的子节点数目，  
	- xNode 为当前子节点  
	*/  
}
```

### stringXmlObject.eachEle(查询参数表) <a id="stringXmlObject.eachEle" href="#stringXmlObject.eachEle">&#x23;</a>
eachQuery 方法的别名。  
创建搜索并遍历标签元素（element）的迭代器。

### stringXmlObject.eachQuery() <a id="stringXmlObject.eachQuery" href="#stringXmlObject.eachQuery">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.eachQuery(查询参数表) <a id="stringXmlObject.eachQuery" href="#stringXmlObject.eachQuery">&#x23;</a>

```aardio
for ele in stringXmlObject.eachQuery(tagName="img"/*创建搜索并遍历元素的迭代器，内部调用 queryEles 方法。  

参数 @1 指定一个表对象，  
该参数表可包含一个或多个键值，用于匹配节点的属性值,  
可使用tagName属性指定节点的标签名,  
可使用parent属性指定开始查询节点的父节点，parent可以是ID或者节点对象。  
属性值使用 string.cmpMatch 函数进行比对，  
> 等价于调用string.cmp函数进行忽略大小写的比较,  
> 并且在失败后调用 string.match 函数使用模式匹配语法进行进行部分匹配。  
> 仍然失败则转为小写并使用模式语法进行部分匹配（请避免使用`\W`等大写表示补集的模式语法）。  

注意在匹配节点属性时有几个例外：  
parent属性不使用模式匹配进行比对，  
如果 tagName,id,name 属性指定的值不含标点则执行忽略大小写的完全匹配（禁用模式匹配和部分匹配）*/){  

}
```

### stringXmlObject.eachTag() <a id="stringXmlObject.eachTag" href="#stringXmlObject.eachTag">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.eachTag(标签名) <a id="stringXmlObject.eachTag" href="#stringXmlObject.eachTag">&#x23;</a>

```aardio
for ele in stringXmlObject.eachTag(/*搜索并遍历匹配指定标签名（tagName）的元素（element）。  

参数 @1 忽略大小写并执行完全匹配（禁用模式匹配与部分匹配）*/){  

}
```

### stringXmlObject.encoding <a id="stringXmlObject.encoding" href="#stringXmlObject.encoding">&#x23;</a>
源文本字符集

### stringXmlObject.enumNodes(枚举函数,搜索标签名) <a id="stringXmlObject.enumNodes" href="#stringXmlObject.enumNodes">&#x23;</a>

```aardio
stringXmlObject.enumNodes(   
	function(parentElement,index,tagName,childCount,xNode){   

	},/*可选指定要查找的标签名（tagName），忽略大小写  
回调函数返回非 null 值时退出枚举，并返回回调函数的所有返回值*/  
)
```

### stringXmlObject.findChild(标签名) <a id="stringXmlObject.findChild" href="#stringXmlObject.findChild">&#x23;</a>
查找第一个匹配参数 @1 指定标签名（tagName）的节点。  
匹配时忽略大小写，如果参数没有指定命名空间则忽略目标节点的命名空间。

### stringXmlObject.findChildren(标签名) <a id="stringXmlObject.findChildren" href="#stringXmlObject.findChildren">&#x23;</a>
查找所有匹配参数 @1 指定标签名（tagName）的节点，返回数组。  
匹配时忽略大小写，如果参数没有指定命名空间则忽略目标节点的命名空间。

### stringXmlObject.getAttribute() <a id="stringXmlObject.getAttribute" href="#stringXmlObject.getAttribute">&#x23;</a>
取属性值,  
参数中指定属性名字,属性名忽略大小写,  
如果通过下标或成员操作符直接获取属性时区分大小写的

### stringXmlObject.getEle("字符串参数") <a id="stringXmlObject.getEle" href="#stringXmlObject.getEle">&#x23;</a>
获取指定 `id` 属性的标签元素（element）。  
参数 @1 指定元素 `id` 属性的值,忽略大小写,支持模式匹配规则

### stringXmlObject.getEleByTag() <a id="stringXmlObject.getEleByTag" href="#stringXmlObject.getEleByTag">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.getEleByTag(标签名) <a id="stringXmlObject.getEleByTag" href="#stringXmlObject.getEleByTag">&#x23;</a>
获取具有指定标签名（tagName）的首个标签元素（element）。  
参数忽略大小写并执行完全匹配（禁用模式匹配与部分匹配）。

### stringXmlObject.getEles("字符串参数") <a id="stringXmlObject.getEles" href="#stringXmlObject.getEles">&#x23;</a>
获取所有指定相同 `name` 属性的标签元素（element），返回值为数组。  
即使找不到节点,也会返回空数组,  
参数指定元素的 name 属性，忽略大小写，支持模式匹配规则

### stringXmlObject.getElesByTag() <a id="stringXmlObject.getElesByTag" href="#stringXmlObject.getElesByTag">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.getElesByTag(标签名) <a id="stringXmlObject.getElesByTag" href="#stringXmlObject.getElesByTag">&#x23;</a>
获取具有指定标签名（tagName）的全部标签元素（element），返回值为数组。  
即使找不到节点,此函数也会返回一个空数组。  
参数忽略大小写并执行完全匹配（禁用模式匹配与部分匹配）。

### stringXmlObject.getParent() <a id="stringXmlObject.getParent" href="#stringXmlObject.getParent">&#x23;</a>
获取父节点

### stringXmlObject.innerText() <a id="stringXmlObject.innerText" href="#stringXmlObject.innerText">&#x23;</a>
返回节点内部文本或 CDATA 节点文本。  
可作为属性直接返回文本，也可以作为方法调用（onwerCall）。  
如果当前对象是 string.html 对象（继承自 string.xml ），则执行以下操作：  
- 具有 tagName 的普通元素内文本去除首尾空白与换行，压缩中间的空白与换行为单个空格  
- 除常见的内联元素以外的其他具有 tagName 的元素在首尾边缘添加换行  
- br 元素转换为单个换行  

注意这个函数在处理时并不会事先移除 head,style,script 等元素

### stringXmlObject.innerXml() <a id="stringXmlObject.innerXml" href="#stringXmlObject.innerXml">&#x23;</a>
将子节点转换 XML 代码（string.html 返回 HTML）。  
可作为属性直接返回 XML / HTML，也可以作为方法调用（onwerCall）。  
如果调用参数 @1 为 true 则缩进格式化返回的 XML 代码,  
可选在参数 @2 中自定义换行符

### stringXmlObject.localTagName <a id="stringXmlObject.localTagName" href="#stringXmlObject.localTagName">&#x23;</a>
保留原始大小写（与 tagName 一致，只是去掉了命名空间前缀）

### stringXmlObject.outerXml() <a id="stringXmlObject.outerXml" href="#stringXmlObject.outerXml">&#x23;</a>
转换为 XML 代码（string.html 返回 HTML）。  
可作为属性直接返回 XML / HTML，也可以作为方法调用（onwerCall）。  
如果调用参数 @1 为 true 则缩进格式化返回的 XML 代码,  
可选在参数 @2 中自定义换行符

### stringXmlObject.pushElement() <a id="stringXmlObject.pushElement" href="#stringXmlObject.pushElement">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.pushElement(节点属性表) <a id="stringXmlObject.pushElement" href="#stringXmlObject.pushElement">&#x23;</a>

```aardio
stringXmlObject.pushElement(  
    tagName =   
    cdata =   
    text = /*注意text,cdata,tagName三个属性只能指定一个,  
可选使用参数@2指定新增节点的位置,不指定则添加到子节点数组尾部,  
返回新增的节点对象*/  
)
```

### stringXmlObject.pushXml() <a id="stringXmlObject.pushXml" href="#stringXmlObject.pushXml">&#x23;</a>
将字符串参数@1中指定的XML添加到当前节点的子节点,  
可选用参数@2指定新节点的位置,不指定则添加到子节点数组尾部,  
返回新增XML中最后一个根节点

[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.queryEle() <a id="stringXmlObject.queryEle" href="#stringXmlObject.queryEle">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.queryEle(查询参数表) <a id="stringXmlObject.queryEle" href="#stringXmlObject.queryEle">&#x23;</a>
搜索标签元素（element），  
此函数调用 queryEles 方法取第 1 个元素。  
参数@1用一个表对象指定搜索条件。  

该参数表可包含一个或多个键值，用于匹配节点的属性值,  
可使用tagName属性指定节点的标签名,  
可使用parent属性指定开始查询节点的父节点，parent可以是ID或者节点对象。  
属性值使用 string.cmpMatch 函数进行比对，  
> 等价于调用string.cmp函数进行忽略大小写的比较,  
> 并且在失败后调用 string.match 函数使用模式匹配语法进行进行部分匹配。  
> 仍然失败则转为小写并使用模式语法进行部分匹配（请避免使用`\W`等大写表示补集的模式语法）。  

注意在匹配节点属性时有几个例外：  
parent属性不使用模式匹配进行比对，  
tagName,id,name属性如果匹配值不含标点则使用忽略大小写的完全比对（禁用模式匹配和部分匹配）

### stringXmlObject.queryEles <a id="stringXmlObject.queryEles" href="#stringXmlObject.queryEles">&#x23;</a>
搜索标签元素（element），该函数返回的是一个数组。  
即使找不到节点，此函数也会返回一个空数组。  

queryEle,eachQuery,eachEle 等方法都是调用 queryEles，  
因此支持的相同的参数写法（参数可以是表也可以是简单 CSS 选择器 ）

### stringXmlObject.queryEles() <a id="stringXmlObject.queryEles" href="#stringXmlObject.queryEles">&#x23;</a>
[返回对象:stringXmlObject](#stringXmlObject)

### stringXmlObject.queryEles(selectors) <a id="stringXmlObject.queryEles" href="#stringXmlObject.queryEles">&#x23;</a>
参数 @1 指定字符串时可支持有限的简单 CSS 选择器：  
tagName, .class, [attr], #id ，例如 "div#id" 。  
解析后的查询条件仍然会被被换为表参数，查询值可使用 aardio 模式匹配语法。  

解析 selectors 参数的代码非常简单（只有几句代码），  
因此不支持复杂语法以及多层级选择器

### stringXmlObject.queryEles(查询参数表) <a id="stringXmlObject.queryEles" href="#stringXmlObject.queryEles">&#x23;</a>
参数@1指定一个表对象，  
该参数表可包含一个或多个键值，用于匹配节点的属性值。  
可使用 tagName 属性指定节点的标签名。  
可使用parent属性指定开始查询节点的父节点，parent可以是ID或者节点对象。  
属性值使用 string.cmpMatch 函数进行比对，  
> 等价于调用string.cmp函数进行忽略大小写的比较,  
> 并且在失败后调用 string.match 函数使用模式匹配语法进行进行部分匹配。  
> 仍然失败则转为小写并使用模式语法进行部分匹配（请避免使用`\W`等大写表示补集的模式语法）。  

注意在匹配节点属性时有几个例外：  
parent属性不使用模式匹配进行比对，  
tagName,id,name属性如果匹配值不含标点则使用忽略大小写的完全比对（禁用模式匹配和部分匹配）

### stringXmlObject.remove() <a id="stringXmlObject.remove" href="#stringXmlObject.remove">&#x23;</a>
如果存在父节点,在父节点中移除此节点

### stringXmlObject.tagName <a id="stringXmlObject.tagName" href="#stringXmlObject.tagName">&#x23;</a>
节点标签名，文本节点无此属性

### stringXmlObject.text <a id="stringXmlObject.text" href="#stringXmlObject.text">&#x23;</a>
文本节点有此属性。  
已执行NCR 解码并已取消常用 XML/HTML 实体转义
