cishu-data-format 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -7
- package/package.json +1 -1
- package/src/index.js +121 -10
package/README.md
CHANGED
|
@@ -1,13 +1,154 @@
|
|
|
1
1
|
# cishu-data-format
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
辞书处理 XML 与 JSON 数据格式转换的 NPM 工具库。
|
|
4
4
|
|
|
5
5
|
## 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install cishu-data-format
|
|
9
|
+
```
|
|
9
10
|
|
|
10
|
-
##
|
|
11
|
+
## 使用说明
|
|
12
|
+
|
|
13
|
+
本工具包支持 ES Modules (ESM) 导入。
|
|
14
|
+
|
|
15
|
+
### 1. 导入方法
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
// 方式一:导入命名函数(推荐)
|
|
19
|
+
import { xmlToJson, jsonToXml } from 'cishu-data-format';
|
|
20
|
+
|
|
21
|
+
// 方式二:导入默认对象
|
|
22
|
+
import cishuFormat from 'cishu-data-format';
|
|
23
|
+
// 使用 cishuFormat.xmlToJson(...) 或 cishuFormat.jsonToXml(...)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. XML 转 JSON (`xmlToJson`)
|
|
27
|
+
|
|
28
|
+
将 XML 字符串转换为特定的 JSON 树形结构。
|
|
29
|
+
|
|
30
|
+
#### 参数
|
|
31
|
+
- `xml` (`string`): 待转换的 XML 字符串。
|
|
32
|
+
|
|
33
|
+
#### 返回值
|
|
34
|
+
- `Object | Array`: 解析后的 JSON 节点。如果 XML 根节点只有一个,则返回该节点对象;如果有多个并列根节点,则返回节点数组。
|
|
35
|
+
|
|
36
|
+
#### 示例
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
import { xmlToJson } from 'cishu-data-format';
|
|
40
|
+
|
|
41
|
+
const xmlString = `
|
|
42
|
+
<book id="1" category="fiction">
|
|
43
|
+
<title>Harry Potter</title>
|
|
44
|
+
<author>J.K. Rowling</author>
|
|
45
|
+
<price currency="USD">29.99</price>
|
|
46
|
+
<description />
|
|
47
|
+
</book>
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
const json = xmlToJson(xmlString);
|
|
51
|
+
console.log(JSON.stringify(json, null, 2));
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**输出 JSON 结构:**
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"type": "element",
|
|
58
|
+
"name": "book",
|
|
59
|
+
"attributes": {
|
|
60
|
+
"id": "1",
|
|
61
|
+
"category": "fiction"
|
|
62
|
+
},
|
|
63
|
+
"children": [
|
|
64
|
+
{
|
|
65
|
+
"type": "element",
|
|
66
|
+
"name": "title",
|
|
67
|
+
"attributes": {},
|
|
68
|
+
"children": [
|
|
69
|
+
{
|
|
70
|
+
"type": "text",
|
|
71
|
+
"text": "Harry Potter"
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"type": "element",
|
|
77
|
+
"name": "author",
|
|
78
|
+
"attributes": {},
|
|
79
|
+
"children": [
|
|
80
|
+
{
|
|
81
|
+
"type": "text",
|
|
82
|
+
"text": "J.K. Rowling"
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"type": "element",
|
|
88
|
+
"name": "price",
|
|
89
|
+
"attributes": {
|
|
90
|
+
"currency": "USD"
|
|
91
|
+
},
|
|
92
|
+
"children": [
|
|
93
|
+
{
|
|
94
|
+
"type": "text",
|
|
95
|
+
"text": "29.99"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"type": "element",
|
|
101
|
+
"name": "description",
|
|
102
|
+
"attributes": {},
|
|
103
|
+
"children": []
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
### 3. JSON 转 XML (`jsonToXml`)
|
|
112
|
+
|
|
113
|
+
将符合上述结构的 JSON 树形对象转换回 XML 字符串,且会自动对属性和文本内容进行安全转义(处理 `&`, `<`, `>`, `"` 字符)。
|
|
114
|
+
|
|
115
|
+
#### 参数
|
|
116
|
+
- `node` (`Object`): 符合格式的 JSON 节点对象(包含 `type`, `name`, `attributes`, `children` 或 `text`)。
|
|
117
|
+
|
|
118
|
+
#### 返回值
|
|
119
|
+
- `string`: 转换后的 XML 字符串。
|
|
120
|
+
|
|
121
|
+
#### 示例
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
import { jsonToXml } from 'cishu-data-format';
|
|
125
|
+
|
|
126
|
+
const jsonNode = {
|
|
127
|
+
type: "element",
|
|
128
|
+
name: "book",
|
|
129
|
+
attributes: { id: "1" },
|
|
130
|
+
children: [
|
|
131
|
+
{
|
|
132
|
+
type: "element",
|
|
133
|
+
name: "title",
|
|
134
|
+
attributes: {},
|
|
135
|
+
children: [{ type: "text", text: "Harry & Potter" }]
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const xmlString = jsonToXml(jsonNode);
|
|
141
|
+
console.log(xmlString);
|
|
142
|
+
// 输出: <book id="1"><title>Harry & Potter</title></book>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 开发者发布指南
|
|
148
|
+
|
|
149
|
+
如果您需要发布或更新此 NPM 包,可参考以下步骤:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
11
152
|
# 1. 在项目根目录初始化(如果还没做)
|
|
12
153
|
npm init -y
|
|
13
154
|
|
|
@@ -16,14 +157,14 @@ npm login
|
|
|
16
157
|
|
|
17
158
|
# 3. 验证是否登录成功
|
|
18
159
|
npm whoami
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# 修改版本号(推荐方式)
|
|
160
|
+
|
|
161
|
+
# 4. 修改版本号(推荐方式)
|
|
22
162
|
npm version patch # 1.0.0 -> 1.0.1
|
|
23
163
|
# 或
|
|
24
164
|
npm version minor # 1.0.0 -> 1.1.0
|
|
25
165
|
# 或
|
|
26
166
|
npm version major # 1.0.0 -> 2.0.0
|
|
27
167
|
|
|
28
|
-
#
|
|
29
|
-
npm publish
|
|
168
|
+
# 5. 发布到 npm
|
|
169
|
+
npm publish --access public
|
|
170
|
+
```
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,20 +1,131 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @param {string}
|
|
4
|
-
* @returns {
|
|
2
|
+
* 将 XML 字符串转换为 JSON 对象结构
|
|
3
|
+
* @param {string} xml - XML 字符串
|
|
4
|
+
* @returns {Object|Array} 解析后的 JSON 节点或节点数组
|
|
5
5
|
*/
|
|
6
|
-
export function
|
|
7
|
-
|
|
6
|
+
export function xmlToJson(xml) {
|
|
7
|
+
xml = xml.trim();
|
|
8
|
+
const tagRegex = /<([^>]+)>/g;
|
|
9
|
+
let lastIndex = 0;
|
|
10
|
+
|
|
11
|
+
const root = { name: null, attributes: {}, children: [], text: "" };
|
|
12
|
+
const stack = [root];
|
|
13
|
+
|
|
14
|
+
function parseAttributes(str) {
|
|
15
|
+
const attrs = {};
|
|
16
|
+
const attrRegex = /(\w[\w:-]*)\s*=\s*"([^"]*)"/g;
|
|
17
|
+
let m;
|
|
18
|
+
while ((m = attrRegex.exec(str))) {
|
|
19
|
+
attrs[m[1]] = m[2];
|
|
20
|
+
}
|
|
21
|
+
return attrs;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let match;
|
|
25
|
+
while ((match = tagRegex.exec(xml))) {
|
|
26
|
+
const textBetween = xml.substring(lastIndex, match.index);
|
|
27
|
+
lastIndex = tagRegex.lastIndex;
|
|
28
|
+
|
|
29
|
+
if (textBetween.trim()) {
|
|
30
|
+
const node = stack[stack.length - 1];
|
|
31
|
+
node.children.push({
|
|
32
|
+
type: "text",
|
|
33
|
+
text: textBetween.trim()
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const tag = match[1].trim();
|
|
38
|
+
|
|
39
|
+
// 处理结束标签 </xxx>
|
|
40
|
+
if (tag.startsWith("/")) {
|
|
41
|
+
stack.pop();
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 判断是否为自闭合标签 <xxx />
|
|
46
|
+
const selfClosing = tag.endsWith("/");
|
|
47
|
+
|
|
48
|
+
// 提取标签名
|
|
49
|
+
const parts = tag.replace(/\/$/, "").split(/\s+/);
|
|
50
|
+
const tagName = parts[0];
|
|
51
|
+
|
|
52
|
+
const attrs = parseAttributes(tag);
|
|
53
|
+
|
|
54
|
+
const newNode = {
|
|
55
|
+
type: "element",
|
|
56
|
+
name: tagName,
|
|
57
|
+
attributes: attrs,
|
|
58
|
+
children: []
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const parent = stack[stack.length - 1];
|
|
62
|
+
parent.children.push(newNode);
|
|
63
|
+
|
|
64
|
+
if (!selfClosing) {
|
|
65
|
+
stack.push(newNode);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return root.children.length === 1 ? root.children[0] : root.children;
|
|
8
70
|
}
|
|
9
71
|
|
|
10
72
|
/**
|
|
11
|
-
*
|
|
73
|
+
* XML 内容转义
|
|
74
|
+
* @param {string} str - 待转义的 XML 文本内容
|
|
75
|
+
* @returns {string} 转义后的文本
|
|
12
76
|
*/
|
|
13
|
-
|
|
14
|
-
return
|
|
77
|
+
function escapeXml(str) {
|
|
78
|
+
return String(str)
|
|
79
|
+
.replace(/&/g, "&")
|
|
80
|
+
.replace(/</g, "<")
|
|
81
|
+
.replace(/>/g, ">");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 属性值转义
|
|
86
|
+
* @param {string} str - 待转义的属性值
|
|
87
|
+
* @returns {string} 转义后的属性值
|
|
88
|
+
*/
|
|
89
|
+
function escapeAttr(str) {
|
|
90
|
+
return String(str)
|
|
91
|
+
.replace(/&/g, "&")
|
|
92
|
+
.replace(/"/g, """)
|
|
93
|
+
.replace(/</g, "<");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 将 JSON 对象结构转换为 XML 字符串
|
|
98
|
+
* @param {Object} node - 符合结构的 JSON 节点
|
|
99
|
+
* @returns {string} XML 字符串
|
|
100
|
+
*/
|
|
101
|
+
export function jsonToXml(node) {
|
|
102
|
+
// 文本节点
|
|
103
|
+
if (node.type === "text") {
|
|
104
|
+
return escapeXml(node.text || "");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 处理属性
|
|
108
|
+
const attrs = Object.entries(node.attributes || {})
|
|
109
|
+
.map(([key, value]) => `${key}="${escapeAttr(value)}"`)
|
|
110
|
+
.join(" ");
|
|
111
|
+
|
|
112
|
+
const hasAttrs = attrs.length > 0;
|
|
113
|
+
const openTag = hasAttrs ? `<${node.name} ${attrs}>` : `<${node.name}>`;
|
|
114
|
+
|
|
115
|
+
// 子节点
|
|
116
|
+
const children = (node.children || [])
|
|
117
|
+
.map(child => jsonToXml(child))
|
|
118
|
+
.join("");
|
|
119
|
+
|
|
120
|
+
// 如果没有 children 且没有文本 → 可能写成自闭合
|
|
121
|
+
if (!children) {
|
|
122
|
+
return hasAttrs ? `<${node.name} ${attrs}/>` : `<${node.name}/>`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return `${openTag}${children}</${node.name}>`;
|
|
15
126
|
}
|
|
16
127
|
|
|
17
128
|
export default {
|
|
18
|
-
|
|
19
|
-
|
|
129
|
+
xmlToJson,
|
|
130
|
+
jsonToXml
|
|
20
131
|
};
|