json是网络中一种通用的数据传输格式,在某些时候需要将json数据格式转化成xml,这里发布自己的一个实现过程.
分析过程包括词法分析和语法分析 构建xml三个部分,语法分析采用采用LL型自上到下的方式.
json是网络中一种通用的数据传输格式,在某些时候需要将json数据格式转化成xml,这里发布自己的一个实现过程.
分析过程包括词法分析和语法分析 构建xml三个部分,语法分析采用采用LL型自上到下的方式.
词法分析中需要的基本单位 有Token 类:表示一个词 TokenType
定义

Code
enum TokenType
{
KEYVALUE,
VALUE,
VALUELIST,
OBJECTLIST,
ID,
EXPR,//:
BIG_LEFT_BRACKET,//{
BIG_RIGHT_BRACKET,//}
MID_LEFT_BRACKET,//[
MID_RIGHT_BRACKET,//]
COMMA,//,
STRING//"xxx"
}
json语法分析过程 值通常的形式为
var v = {id:100,id:{id:[20,5]}}
var v = 13;
var v=[a,b,c];
定义的范式为,值,对象序列,键值,值序列,它们的对应关系为
//值 => id |{对象序列}|[值序列] --对应MathValue()方法解析
//对象序列=>键值|对象序列,键值 --对应MathObjectList()方法解析;
//键值=>id:值
//值序列=>值|值序列,值 --对应MathValueList()方法解析;
(说明:源代码书写有误 Math->应该是Match)
就是说MathValue()匹配json的值

Code
1
/**//// <summary>
2
/// [ooo]{ID|}[/ooo]
3
/// </summary>
4
/// <param name="ooo"></param>
5
/// <returns></returns>
6
private void MathValue(XmlNode ooo)
7
{
8
temp = GetInToken();
9
if (temp.Type == TokenType.ID)
10
{
11
ooo.InnerText = temp.Segment;
12
}
13
else if (temp.Type == TokenType.BIG_LEFT_BRACKET)
14
{
15
16
MathObjectList(ooo);
17
temp = GetInToken();
18
if (temp.Type != TokenType.BIG_RIGHT_BRACKET)
19
throw new Exception("不匹配");
20
//操作从堆栈中处理
21
}
22
else if (temp.Type == TokenType.MID_LEFT_BRACKET)
23
{
24
//返回节点ast
25
MathValueList(ooo, lastheader);
26
temp = GetInToken();
27
if (temp.Type != TokenType.MID_RIGHT_BRACKET)
28
throw new Exception("不匹配");
29
//从堆栈中构建
30
}
31
else
32
throw new Exception("不匹配");
33
}

Code
1
private void MathObjectList(XmlNode root)
2
{
3
temp = GetInToken();
4
if (temp.Type != TokenType.ID)
5
throw new Exception("不匹配");
6
string id = temp.Segment;
7
this.lastheader = id;
8
9
temp = GetInToken();
10
if (temp.Type != TokenType.EXPR)
11
throw new Exception("不匹配");
12
//MathValue();
13
if (PL(1).Type == TokenType.MID_LEFT_BRACKET)
14
{
15
this.lastheader = id;
16
//if(root.ParentNode==null)
17
MathValue(root);
18
}
19
else
20
{
21
22
XmlElement elem = doc.CreateElement(id);
23
root.AppendChild(elem);
24
MathValue(elem);
25
26
}
27
//这里不能确定是数组还是 数组就是在root ,ID 就是创建 id,用innertext
28
/**/////{ 就是创建id 的节点, 用innerxml
29
//MathValue(elem);
30
31
32
if (PL(1).Type == TokenType.COMMA)
33
{
34
temp = GetInToken();
35
MathObjectList(root);
36
}
37
}
38
private void MathValueList(XmlNode xml,string header)
39
{
40
if (string.IsNullOrEmpty(header))
41
header = "Value";
42
XmlNode node1 = doc.CreateElement(header);
43
MathValue(node1);
44
xml.AppendChild(node1);
45
if (PL(1).Type == TokenType.COMMA)
46
{
47
temp = GetInToken();
48
MathValueList(xml,header);
49
}
50
51
}
代码中在语法分析的同时进行了xml树的创造,调用的参数为xml的父节点
这样就完成了一个简单的分析,调用的方法为:
Translator translator = new Translator();
translator.Tranfile(this.richTextBox1.Text);
this.richTextBox2.Text = translator.doc.OuterXml;
处理网上的一个示例程序
{
name:"中国",
province:[
{
name:"黑龙江",
citys:{
city:["哈尔滨","大庆"]
}
},
{
name:"广东",
citys:{
city:["广州","深圳","珠海"]
}
},
{
name:"台湾",
citys:{
city:["台北","高雄"]
}
},
{
name:"新 疆",
citys:{
city:["乌鲁木齐"]
}
}
]
}
输出结果(格式化后):
源代码下载