在不同格式的XML文档之间相互转换(二)加工源数据

上篇日志展示了文档转换的基本功能,即根据指定的路径从源文档中取出数据,在使用模板生成目标文档的同时填充数据到相应位置。应用中,这种简单的数据转移或者叫复制并不能满足我们的要求。我们常常需要将数据进行适当加工后再填充到目标文档,简单说,最终数据必须由代码动态生成。对于student.src.xml,现在修改如下。

 student.src.xml

1 <?xml version="1.0" encoding="utf-8"?>
2  <students>
3 <student sn="001">
4 <name>张刚</name>
5 <age>19</age>
6 <subjects>
7 <subject>
8 <name>高等数学</name><score>80</score>
9 </subject>
10 <subject>
11 <name>操作系统</name><score>92</score>
12 </subject>
13 <subject>
14 <name>哲学</name><score>70</score>
15 </subject>
16 </subjects>
17 </student>
18 <student sn="002">
19 <name>李明</name>
20 <age>20</age>
21 <subjects>
22 <subject>
23 <name>高等数学</name><score>90</score>
24 </subject>
25 <subject>
26 <name>操作系统</name><score>95</score>
27 </subject>
28 <subject>
29 <name>哲学</name><score>85</score>
30 </subject>
31 </subjects>
32 </student>
33 <student sn="003">
34 <name>孙伟</name>
35 <age>18</age>
36 <subjects>
37 <subject>
38 <name>高等数学</name><score>79</score>
39 </subject>
40 <subject>
41 <name>操作系统</name><score>83</score>
42 </subject>
43 <subject>
44 <name>哲学</name><score>69</score>
45 </subject>
46 </subjects>
47 </student>
48 <student sn="004">
49 <name>刘鑫</name>
50 <age>18</age>
51 <subjects>
52 <subject>
53 <name>高等数学</name><score>60</score>
54 </subject>
55 <subject>
56 <name>操作系统</name><score>75</score>
57 </subject>
58 <subject>
59 <name>哲学</name><score>95</score>
60 </subject>
61 </subjects>
62 </student>
63 <student sn="005">
64 <name>高健</name>
65 <age>18</age>
66 <subjects>
67 <subject>
68 <name>高等数学</name><score>72</score>
69 </subject>
70 <subject>
71 <name>操作系统</name><score>45</score>
72 </subject>
73 <subject>
74 <name>哲学</name><score>50</score>
75 </subject>
76 </subjects>
77 </student>
78 <student sn="006">
79 <name>王晨</name>
80 <age>18</age>
81 <subjects>
82 <subject>
83 <name>高等数学</name><score>80</score>
84 </subject>
85 <subject>
86 <name>操作系统</name><score>81</score>
87 </subject>
88 <subject>
89 <name>哲学</name><score>70</score>
90 </subject>
91 </subjects>
92 </student>
93  </students>

 

现在我们需要统计每个人各科成绩的总分和平均分,然后按照由高到低的顺序排名。新的模板文档student.tpl.xml如下。

 student.tpl.xml

1 <?xml version="1.0" encoding="utf-8"?>
2  <template rootname="table">
3 <attribute name="border" expression="true">
4 <expression>
5 <paramlist>
6 <param name="#ctrlid#" path="/" attr="controlguid" />
7 <param name="#srcdocguid#" path="/" attr="guid" />
8 </paramlist>
9 <statement>
10 <![CDATA[
11 var ctrl = $$("#ctrlid#");
12 var srcDoc = $$("#srcdocguid#");
13 ctrl.$$secret.codebehind.scoreArray = [];
14 ctrl.$$secret.codebehind.totalStudent = 0;
15 ctrl.$$secret.codebehind.totalSubject = 0;
16 var totalStudent , totalSubject;
17 var studentList , subjectList;
18 studentList = srcDoc.documentElement.getElementsByTagName("student");
19 totalStudent = ctrl.$$secret.codebehind.totalStudent = studentList.length;
20 totalSubject = ctrl.$$secret.codebehind.totalSubject = (studentList.length != 0 && studentList.item(0).getElementsByTagName("subject").length != 0) ? studentList.item(0).getElementsByTagName("subject").length : 0;
21 var totalScore;
22 for(var si = 0 ; si < totalStudent ; si++){
23 totalScore = 0;
24 for(var sj = 0 ; sj < totalSubject ; sj++){
25 totalScore += parseFloat(studentList.item(si).getElementsByTagName("subject").item(sj).getElementsByTagName("score").item(0).firstChild.nodeValue);
26 }
27 ctrl.$$secret.codebehind.scoreArray.push
28 (
29 {
30 "sn" : studentList.item(si).getAttribute("sn"),
31 "name" : $System.XML.XMLUtil.XElement.getFirstElementChildByTagName(studentList.item(si) , "name").firstChild.nodeValue,
32 "total" : totalScore,
33 "average" : Math.round(totalScore * 10 / totalSubject) / 10
34 }
35 );
36 }
37 ctrl.$$secret.codebehind.scoreArray.sort
38 (
39 function(a , b){
40 if(a.total == b.total){
41 return 0;
42 }
43 if(a.total > b.total){
44 return 1;
45 }
46 return -1;
47 }
48 );
49 ctrl.$$secret.codebehind.scoreArray.reverse();
50 var border;
51 border = 1;
52 ]]>
53 </statement>
54 </expression>
55 </attribute>
56 <element name="tr">
57 <attribute name="bgcolor" value="#6699FF" />
58 <element name="td">
59 <text>名次</text>
60 </element>
61 <element name="td">
62 <text>学号</text>
63 </element>
64 <element name="td">
65 <text>姓名</text>
66 </element>
67 <element name="td">
68 <text>总分</text>
69 </element>
70 <element name="td">
71 <text>平均分</text>
72 </element>
73 </element>
74 <for>
75 <expression>
76 <paramlist>
77 <param name="#ctrlid#" path="/" attr="controlguid" />
78 </paramlist>
79 <statement>
80 <![CDATA[
81 $$("#ctrlid#").$$secret.codebehind.iterI = 0;
82 var returnValue;
83 returnValue = "0," + $$("#ctrlid#").$$secret.codebehind.scoreArray.length;
84 ]]>
85 </statement>
86 </expression>
87 <element name="tr">
88 <element name="td">
89 <text expression="true">
90 <expression>
91 <paramlist>
92 <param name="#ctrlid#" path="/" attr="controlguid" />
93 </paramlist>
94 <statement>
95 <![CDATA[
96 var order;
97 order = $$("#ctrlid#").$$secret.codebehind.iterI + 1;
98 ]]>
99 </statement>
100 </expression>
101 </text>
102 </element>
103 <element name="td">
104 <text expression="true">
105 <expression>
106 <paramlist>
107 <param name="#ctrlid#" path="/" attr="controlguid" />
108 </paramlist>
109 <statement>
110 <![CDATA[
111 var sn;
112 sn = $$("#ctrlid#").$$secret.codebehind.scoreArray[$$("#ctrlid#").$$secret.codebehind.iterI].sn;
113 ]]>
114 </statement>
115 </expression>
116 </text>
117 </element>
118 <element name="td">
119 <text expression="true">
120 <expression>
121 <paramlist>
122 <param name="#ctrlid#" path="/" attr="controlguid" />
123 </paramlist>
124 <statement>
125 <![CDATA[
126 var sn;
127 sn = $$("#ctrlid#").$$secret.codebehind.scoreArray[$$("#ctrlid#").$$secret.codebehind.iterI].name;
128 ]]>
129 </statement>
130 </expression>
131 </text>
132 </element>
133 <element name="td">
134 <text expression="true">
135 <expression>
136 <paramlist>
137 <param name="#ctrlid#" path="/" attr="controlguid" />
138 </paramlist>
139 <statement>
140 <![CDATA[
141 var sn;
142 sn = $$("#ctrlid#").$$secret.codebehind.scoreArray[$$("#ctrlid#").$$secret.codebehind.iterI].total;
143 ]]>
144 </statement>
145 </expression>
146 </text>
147 </element>
148 <element name="td">
149 <text expression="true">
150 <expression>
151 <paramlist>
152 <param name="#ctrlid#" path="/" attr="controlguid" />
153 </paramlist>
154 <statement>
155 <![CDATA[
156 var sn;
157 sn = $$("#ctrlid#").$$secret.codebehind.scoreArray[$$("#ctrlid#").$$secret.codebehind.iterI].average;
158 $$("#ctrlid#").$$secret.codebehind.iterI++;
159 sn;
160 ]]>
161 </statement>
162 </expression>
163 </text>
164 </element>
165 </element>
166 </for>
167  </template>
168

 

这里我们引入了$System.UI.Control类,把一个dom元素简单包装成一个js对象。这个例子中这样做的目的是方便保存转换过程中的公共变量。对于转换过程中保存变量的方法可以有多种,这里只是提供了一种可行性,同时具体实现的优劣这里不做讨论。后面的讨论还可以看到,使用一种标准的方式将模板文档与其父容器关联,一定程度上弱化了文档的通用性,但另一方面,如果要生成能与容器乃至页面互动的DOM结构,总是要做些关联工作的。render方法的工作过程也可以浏览压缩包中相应的js源码。

转换代码如下。

1 var ctrl1 = new $System.UI.Control("div005");
2 var srcdoc = $System.XML.XMLUtil.loadXMLFile("xmltest\\student.src.xml");
3 var tpldoc = $System.XML.XMLUtil.loadXMLFile("xmltest\\student.tpl.xml");
4 ctrl1.renderE(srcdoc , tpldoc);

 

 转换结果如下。

 

 

转换的复杂性通过嵌入模板文档的脚本来实现,也可以为每个脚本块指定参数,转换过程到达脚本块时会使用实参替换对应的占位符,然后执行脚本,将返回值(对最后一行代码求值的结果)插入目标文档要求的位置。

 

代码的试验仍按照上篇日志所述方法进行。

 

 

posted @ 2010-11-19 00:41  lonely~  阅读(666)  评论(0编辑  收藏  举报