XML与XSLT(续)
在之前的XML与XSLT的文章中我曾经提到过使用XSL可以对XML文件中的数据进行查询和筛选的操作,但并没有给出具体的实例,下面我将通过自己实际工作中使用到的代码针对XSLT中的<xsl:Choose>和<xsl:for-each>两个元素进行简单讲述。
在我目前负责的一个项目中使用用XML做为配置文件。其内容如下所示。
<?xml-stylesheettype='text/xsl'href='EForm.xsl'?>
<Eform>
<title>OutLeaveApplication</title>
<FormId>1010</FormId>
<TotalPhase>1</TotalPhase>
<dataTable>T_LEAVE</dataTable>
<HtmlTemplate>1010_html.vm</HtmlTemplate>
<PdaTemplate>1010_pda.vm</PdaTemplate>
<FieldList>
<Fieldname="EmpNo"phase="1"DbFieldName="EmpNo"control="Text">
<ControlAttributesize="10"maxlength="20"/>
<DataFieldType>VARCHAR</DataFieldType>
</Field>
<Fieldname="dept"phase="1"DbFieldName="dept"control="Text">
<ControlAttributesize="10"maxlength="20"/>
<DataFieldType>VARCHAR</DataFieldType>
</Field>
<Fieldname="start_Date"phase="1"DbFieldName="start_Date"control="Text">
<ControlAttributesize="20"maxlength="20"/>
<DataFieldType>VARCHAR</DataFieldType>
</Field>
<Fieldname="start_Time"phase="1"DbFieldName="start_Time"control="Select">
<ControlAttributesize="10"multiple="false"/>
<DataFieldType>VARCHAR</DataFieldType>
<DataSourcetype="text">
<Value>8;9;10;11;12;13;14;15;16;17;18</Value>
</DataSource>
<DefaultValue>8</DefaultValue>
</Field>
<Fieldname="end_Date"phase="1"DbFieldName="end_Date"control="Text">
<ControlAttributesize="20"maxlength="20"/>
<DataFieldType>VARCHAR</DataFieldType>
</Field>
<Fieldname="end_Time"phase="1"DbFieldName="end_Time"control="Select">
<ControlAttributesize="10"multiple="false"/>
<DataFieldType>VARCHAR</DataFieldType>
<DataSourcetype="text">
<Value>8;9;10;11;12;13;14;15;16;17;18</Value>
</DataSource>
<DefaultValue>17</DefaultValue>
</Field>
<Fieldname="total_Time"phase="1"DbFieldName="total_Time"control="Text">
<ControlAttributesize="10"maxlength="20"/>
<DataFieldType>Int</DataFieldType>
</Field>
<Fieldname="leave_type"phase="1"DbFieldName="leave_type"control="Select">
<ControlAttribute/>
<DataFieldType>VARCHAR</DataFieldType>
<DataSourcetype="text">
<DisplayText>OnBusiness;private;sick;annual;maternity;marriage;compassionate;Nursing;Relief</DisplayText>
<Value>0;1;2;3;4;5;6;7;8</Value>
</DataSource>
<DefaultValue>private</DefaultValue>
</Field>
<Fieldname="attach"phase="1"DbFieldName="attach"control="AttachMent">
<ControlAttributetype="file"size="100%"/>
<DataFieldType>VARCHAR</DataFieldType>
</Field>
</FieldList>
<SQLTemplates>
<selectSQL>SELECT*FROMT_LEAVE</selectSQL>
<updateSQL>
<phasestep="1">UPDATET_LEAVESET
EmpNo='$EmpNo',
dept='$dept',
start_Date='$start_Date',
end_Date='$end_Date',
start_Time='$start_Time',
end_Time='$end_Time',
total_Time=$total_Time,
leave_type='$leave_type',
attach='$attach'WHEREDOC_ID=$doc_id</phase>
</updateSQL>
<insertSQL>INSERTINTOT_LEAVE(DOC_ID)VALUES($doc_id)</insertSQL>
<deleteSQL>DELETEFROMT_LEAVEWHEREDOC_ID=$doc_id</deleteSQL>
</SQLTemplates>
</Eform>
这个配置文件中主要记录了三部分的信息,一部分是表单的基本信息,一部分是表单中的字段信息,还有一部分是对应查询,插入,删除和更新的SQL语句。在IE中查看这个配置文件时,其会使用自带的XML解析器对该文件进行解析,看到的是一个树型的数据,对我而言这种查看方式并不方便,于是我自己动手为其编写了一个XSL转换文件。
大家可以看到这个配置文件中有个FieldList结点,这个结点下又有若干个Field子结点,Field结点会依据其属性Control的值决定其下会出现哪些子结点以及哪些属性。我们在进行转换时就需要用到<xsl:for-each>元素对FieldList结点下的子结点进行遍历,同时还需要用到<xsl:choose>元素来判断Field结点Control属性值决定下一步动作。下面就是针对FieldList结点的XSL文件片断。
<divstyle="width:100%;margin:10px0px0px0px">
<tableborder="1"cellspacing="0"cellpadding="2"style="font-size:10pt;width:100%;text-align:center;border-collapse:collapse">
<tr>
<tdcolspan="8"style="font-weight:bold;text-align:center"><xsl:text>FieldList</xsl:text></td>
</tr>
<trstyle="background-color:#DADADA">
<tdstyle="font-weight:bold"><xsl:text>Name</xsl:text></td>
<tdstyle="font-weight:bold"><xsl:text>Phase</xsl:text></td>
<tdstyle="font-weight:bold"><xsl:text>DBField</xsl:text></td>
<tdstyle="font-weight:bold"><xsl:text>Type</xsl:text></td>
<tdstyle="font-weight:bold"><xsl:text>Size/cols</xsl:text></td>
<tdstyle="font-weight:bold"><xsl:text>MaxLength/rows</xsl:text></td>
<tdstyle="font-weight:bold"><xsl:text>Control</xsl:text></td>
<tdstyle="font-weight:bold"><xsl:text>DataSource</xsl:text></td>
</tr>
<xsl:for-eachselect="FieldList/Field">
<tr>
<tdstyle="font-weight:bold;text-align:left;width:150px"><xsl:value-ofselect="@name"/></td>
<tdstyle="width:50px"><xsl:value-ofselect="@phase"/></td>
<tdstyle="text-align:left;width:150px"><xsl:value-ofselect="@DbFieldName"/></td>
<tdstyle="text-align:left;width:80px"><xsl:value-ofselect="DataFieldType"/></td>
<tdstyle="width:50px">
<xsl:choose>
<xsl:whentest="@control="Textarea"">
<xsl:value-ofselect="ControlAttribute/@cols"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-ofselect="ControlAttribute/@size"/>
</xsl:otherwise>
</xsl:choose>
</td>
<tdstyle="width:50px">
<xsl:choose>
<xsl:whentest="@control="Textarea"">
<xsl:value-ofselect="ControlAttribute/@rows"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-ofselect="ControlAttribute/@maxlength"/>
</xsl:otherwise>
</xsl:choose>
</td>
<tdstyle="text-align:left;width:70px"><xsl:value-ofselect="@control"/></td>
<tdstyle="text-align:left">
<xsl:iftest="DataSource">
<B><xsl:value-ofselect="DataSource/@type"/>:</B><xsl:value-ofselect="DataSource/Value"/>
</xsl:if>
</td>
</tr>
</xsl:for-each>
</table>
</div>
我们首先在样式中定义了一个表格做为FieldList的显示容器,当表头定义结束后,就开始遍历其子结点,每个一子结点Field对应着表中的一行。<xsl:for-each>很像程序设计语言中的循环语句,它会逐一访问每一个子结点,直至全部访问完毕。
<tr>
<tdstyle="font-weight:bold;text-align:left;width:150px"><xsl:value-ofselect="@name"/></td>
<tdstyle="width:50px"><xsl:value-ofselect="@phase"/></td>
<tdstyle="text-align:left;width:150px"><xsl:value-ofselect="@DbFieldName"/></td>
<tdstyle="text-align:left;width:80px"><xsl:value-ofselect="DataFieldType"/></td>
<tdstyle="width:50px">
<xsl:choose>
<xsl:whentest="@control="Textarea"">
<xsl:value-ofselect="ControlAttribute/@cols"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-ofselect="ControlAttribute/@size"/>
</xsl:otherwise>
</xsl:choose>
</td>
<tdstyle="width:50px">
<xsl:choose>
<xsl:whentest="@control="Textarea"">
<xsl:value-ofselect="ControlAttribute/@rows"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-ofselect="ControlAttribute/@maxlength"/>
</xsl:otherwise>
</xsl:choose>
</td>
<tdstyle="text-align:left;width:70px"><xsl:value-ofselect="@control"/></td>
<tdstyle="text-align:left">
<xsl:iftest="DataSource">
<B><xsl:value-ofselect="DataSource/@type"/>:</B><xsl:value-ofselect="DataSource/Value"/>
</xsl:if>
</td>
</tr>
</xsl:for-each>
每个单元格的内容都是使用<xsl:value-of select="ChildNodeName">或是<xsl:value-of select="@AttributeName">元素直接读取XML文件中的内容,唯一需要单独处理的就是有两个单元格要依据结点Control属性值的不同读取不同元素的值进行填充显示,这里就用到了<xsl:choose>元素。
<xsl:value-ofselect="ControlAttribute/@cols"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-ofselect="ControlAttribute/@size"/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>元素的用法很像程序设计语言中的Case语句。使用<xsl:when test="">进行条件判断,使用<xsl:otherwise>作为默认处理。需要注意的是在test中进行条件判断时不能直接使用双引号("),而是要使用转义符"代替。这里我们先判断Control属性值是否为“Textarea”,如果是,则选择子结点ControlAttribute的Cols属性输出,否则选择子结点ControlAttribute的Size属性输出。
以上仅是一家之言,还望斧正。
版权声明:本文为博主原创文章,未经博主允许不得转载。