以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 XML源码及示例(仅原创和转载) 』  (http://bbs.xml.org.cn/list.asp?boardid=32)
----  XML卷之实战锦囊  (http://bbs.xml.org.cn/dispbbs.asp?boardid=32&rootid=&id=5421)


--  作者:小鞋子
--  发布时间:2/19/2004 9:12:00 AM

--  XML卷之实战锦囊
特注:原作者:車仔

(1):动态排序
动机:
排序功能让我们页面上的数据显的更人性化,是我们在网站上见过的很普遍的一个功能效果了。以往的自动排序都是用大量的脚本代码来完成的,对一般的爱好者来说这是件困难的事情。然而用XML来处理的话就简单多了。让自己的页面更加绚丽,哈哈,您是不是也心动了呢!

材料:
XML卷之动态排序
有2个文件:paixu.xml 和 paixu.xsl

作用:
在不刷新页面的情况下更据用户自己的需要对数据重新进行排序显示,有效的提高数据互动功能,让自己的页面更加绚丽多彩。  
效果:
浏览这里  
代码:
paixu.xml
<?xml version="1.0" encoding="gb2312" ?>
<?xml-stylesheet type="text/xsl" href="paixu.xsl" ?>
<BlueIdea>
  <team>
    <blue_ID>1</blue_ID>
    <blue_name>Sailflying</blue_name>
    <blue_text>一个简单的排序</blue_text>
    <blue_time>2002-1-11 17:35:33</blue_time>
    <blue_class>XML专题</blue_class>
  </team>
  <team>
    <blue_ID>2</blue_ID>
    <blue_name>flyingbird</blue_name>
    <blue_text>嫁给你,是要你疼的</blue_text>
    <blue_time>2001-09-06 12:45:51</blue_time>
    <blue_class>灌水精华</blue_class>
  </team>
  <team>
    <blue_ID>3</blue_ID>
    <blue_name>苛子</blue_name>
    <blue_text>正则表达式在UBB论坛中的应用</blue_text>
    <blue_time>2001-11-23 21:02:16</blue_time>
    <blue_class>Web 编程精华</blue_class>
  </team>
  <team>
    <blue_ID>4</blue_ID>
    <blue_name>太乙郎</blue_name>
    <blue_text>年末经典分舵聚会完全手册 v0.1</blue_text>
    <blue_time>2000-12-08 10:22:48</blue_time>
    <blue_class>论坛灌水区</blue_class>
  </team>
  <team>
    <blue_ID>5</blue_ID>
    <blue_name>mmkk</blue_name>
    <blue_text>Asp错误信息总汇</blue_text>
    <blue_time>2001-10-13 16:39:05</blue_time>
    <blue_class>javascript脚本</blue_class>
  </team>
</BlueIdea>

paixu.xsl
<?xml version="1.0" encoding="gb2312" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<html>
<head>
<title> XML卷之实战锦囊(1):动态排序</title>
<style>
body,BlueIdea,team,blue_ID,blue_name,blue_text,blue_time,blue_class{ font: 12px "宋体", "Arial", "Times New Roman"; }
table { font-size: 12px; border: 0px double; border-color: #99CC99 #99CC99 #CCCCCC #CCCCCC; cellpadding:3;cellspacing:3; bgcolor:#eeeeee; text-decoration: blink}
span { font-size: 12px; color: red; }
</style>
<script>
function taxis(x)
{
stylesheet=document.XSLDocument;
source=document.XMLDocument;
sortField=document.XSLDocument.selectSingleNode("//@order-by");
sortField.value=x;
Layer1.innerHTML=source.documentElement.transformNode(stylesheet);
}
</script>
</head>
<body>
<p align="center"><span>XML卷之实战锦囊(1):动态排序</span></p>
<div id="Layer1" name="Layer1">
<xsl:apply-templates select="BlueIdea" />
</div>
</body>
</html>
</xsl:template>
<xsl:template match="BlueIdea">
<table width="500" border="1" align="center" cellpadding="1" cellspacing="1" bordercolordark="#ffffff" bordercolorlight="#ADAAAD">
<tr bgcolor="#FFCC99" align="center">
<td style="cursor:s-resize" onClick="taxis('blue_ID')">编号</td>
<td style="cursor:s-resize" onClick="taxis('blue_name')">姓名</td>
<td style="cursor:s-resize" onClick="taxis('blue_text')">主题</td>
<td style="cursor:s-resize" onClick="taxis('blue_time')">发表时间</td>
<td style="cursor:s-resize" onClick="taxis('blue_class')">归类</td>
</tr>
<xsl:apply-templates select="team" order-by="blue_ID"/>
</table>
</xsl:template>
<xsl:template match="team">
<tr align="center">
<xsl:apply-templates select="blue_ID" />
<xsl:apply-templates select="blue_name" />
<xsl:apply-templates select="blue_text" />
<xsl:apply-templates select="blue_time" />
<xsl:apply-templates select="blue_class" />
</tr>
</xsl:template>
<xsl:template match="blue_ID">
<td bgcolor="#eeeeee">
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_name">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_text">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_time">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_class">
<td>
<xsl:value-of />
</td>
</xsl:template>
</xsl:stylesheet>


讲解:
1)paixu.xml 是数据文件,相信大家都不会有问题。
2)paixu.xsl 是格式文件,有几个地方要注意。  
(1)脚本中:

sortField=document.XSLDocument.selectSingleNode("//@order-by");
作用是:找到有属性为order-by的第一个节点,因此它对应的节点就是
<xsl:apply-templates select="team" order-by="blue_ID"/>
因此在初次onLoad的时候order-by的value值是blue_ID。
而我们就是通过重新定义order-by的value值来达到排序的目的。

Layer1.innerHTML=source.documentElement.transformNode(stylesheet);
作用是:转化XML数据后更改Layer1,因此在传出参数'blue_name'后,
<td style="cursor:s-resize" onClick="taxis('blue_name)">姓名</td>
我们将order-by的value值修改为是'blue_name',即以'blue_name'为排序方式。
继而通过重新显示Layer1的innerHTML值来显示新的排序内容。

(2)文本中:

order-by
这个可不能少哦,不然就找不到了,效果嘛,你瞧瞧看吧!!

<?xml version="1.0" encoding="gb2312" ?>
另外说一点:
在大多的XML教科书中所显示的代码中很少会加上encoding="gb2312" ,
因此我们在XML中用到中文的时候会报错,原因就是没有写这个申明。


后记:
大家熟悉动态排序完成思路后会发现,其实我们的实现手法很简单。
就是修改order-by的数值,然后重新显示。
在动态查询和动态分页的功能中我们依然是按照这个思路去完成的。


[此贴子已经被作者于2004-2-19 9:13:43编辑过]

--  作者:小鞋子
--  发布时间:2/19/2004 9:14:00 AM

--  
(2):动态查询
特注:原作者:車仔

动机:
查询功能是我们在网站上见过的最普遍也是最常用的一个功能模块了。以往的信息查询都是连接到数据库的,每一次点击都必须要后台数据库的支持。然而很多情况下用户往往只针对某一部分的数据进行操作,这样不但服务器的负担加重,而且严重的影响用户浏览的速度。

针对这种情况我们需要将用户需要的某一部分数据以XML的方式传递到客户端,用户对这些数据可以很方便的进行操作。既方便了用户,又减轻了服务器数据库的负担。何乐而不为呢!而且这项功能可以通用到其他众多模块,因此添加了这个动态查询功能。

材料:
XML卷之动态查询
有2个文件:search.xml 和 search.xsl

作用:
在不刷新页面的情况下对数据进行过滤筛选,有效的提高数据查询的功能。  
效果:
浏览这里  
代码:
search.xml
<?xml version="1.0" encoding="gb2312" ?>
<?xml-stylesheet type="text/xsl" href="search.xsl" ?>
<BlueIdea>
  <team>
    <blue_ID>1</blue_ID>
    <blue_name>Sailflying</blue_name>
    <blue_text>一个简单的查询</blue_text>
    <blue_time>2002-1-11 17:35:33</blue_time>
    <blue_class>XML专题</blue_class>
  </team>
  <team>
    <blue_ID>2</blue_ID>
    <blue_name>flyingbird</blue_name>
    <blue_text>嫁给你,是要你疼的</blue_text>
    <blue_time>2001-09-06 12:45:51</blue_time>
    <blue_class>灌水精华</blue_class>
  </team>
  <team>
    <blue_ID>3</blue_ID>
    <blue_name>苛子</blue_name>
    <blue_text>正则表达式在UBB论坛中的应用</blue_text>
    <blue_time>2001-11-23 21:02:16</blue_time>
    <blue_class>Web 编程精华</blue_class>
  </team>
  <team>
    <blue_ID>4</blue_ID>
    <blue_name>太乙郎</blue_name>
    <blue_text>年末经典分舵聚会完全手册 v0.1</blue_text>
    <blue_time>2000-12-08 10:22:48</blue_time>
    <blue_class>论坛灌水区</blue_class>
  </team>
  <team>
    <blue_ID>5</blue_ID>
    <blue_name>mmkk</blue_name>
    <blue_text>Asp错误信息总汇</blue_text>
    <blue_time>2001-10-13 16:39:05</blue_time>
    <blue_class>javascript脚本</blue_class>
  </team>
</BlueIdea>

search.xsl
<?xml version="1.0" encoding="gb2312" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<html>
<head>
<title> XML卷之实战锦囊(2):动态查询</title>
<style>
body,BlueIdea,team,blue_ID,blue_name,blue_text,blue_time,blue_class{ font: 12px "宋体", "Arial", "Times New Roman"; }
table { font-size: 12px; border: 0px double; border-color: #99CC99 #99CC99 #CCCCCC #CCCCCC; cellpadding:3;cellspacing:3; bgcolor:#eeeeee; text-decoration: blink}
span { font-size: 12px; color: red; }
</style>
<script>
function searchtext(x)
{
stylesheet=document.XSLDocument;
source=document.XMLDocument;
sortField=document.XSLDocument.selectNodes("//@select");
if (x!="")
{
sortField[1].value="team[blue_ID='"+x+"']";
Layer1.innerHTML=source.documentElement.transformNode(stylesheet);
}
else {alert("请输入筛选条件!");}
}
</script>
</head>
<body>
<p align="center"><span>XML卷之实战锦囊(2):动态查询</span></p>
<div id="Layer1" name="Layer1">
<xsl:apply-templates select="BlueIdea" />
</div>
<hr size="1" width="500" />
<table align="center" cellpadding="0" cellspacing="0" border="0" >
<tr>
<td>
<span >请输入筛选条件 : </span>
blue_ID= <input type="text" name="searchtext" size="1" maxlength="1" />
<input type="button" class="button" onClick="searchtext(document.all.searchtext.value)" value="Search" name="button" />
</td>
</tr>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="BlueIdea">
<table width="500" border="1" align="center" cellpadding="1" cellspacing="1" bordercolordark="#ffffff" bordercolorlight="#ADAAAD">
<tr bgcolor="#FFCC99" align="center">
<td>编号</td>
<td>姓名</td>
<td>主题</td>
<td>发表时间</td>
<td>归类</td>
</tr>
<xsl:apply-templates select="team" order-by="blue_ID"/>
</table>
</xsl:template>
<xsl:template match="team">
<tr align="center">
<xsl:apply-templates select="blue_ID" />
<xsl:apply-templates select="blue_name" />
<xsl:apply-templates select="blue_text" />
<xsl:apply-templates select="blue_time" />
<xsl:apply-templates select="blue_class" />
</tr>
</xsl:template>
<xsl:template match="blue_ID">
<td bgcolor="#eeeeee">
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_name">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_text">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_time">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_class">
<td>
<xsl:value-of />
</td>
</xsl:template>
</xsl:stylesheet>


讲解:
1)search.xml 是数据文件,相信大家都不会有问题。
2)search.xsl 是格式文件,有几个地方要注意。  
(1)脚本中:
sortField=document.XSLDocument.selectNodes("//@select");
作用是:找到所有属性为select的节点。这个和我在动态排序中说到的
sortField=document.XSLDocument.selectSingleNode("//@order-by");
有些不一样了。大家注意这个小小的区别以及各自的功能。


sortField[1].value="team[blue_ID='"+x+"']";
因此sortField[1]就是找到的第二个节点,它对应的节点就是
<xsl:apply-templates select="team" order-by="blue_ID"/>

参数 x 是文本框中输入的数值。
我们将select="team" 的搜索条件修改为select="team[blue_ID='x']"
作用是:增加判断条件,只有blue_ID的数值等于 x 的XML数据才显示出来。
当然大家可以丰富判断的条件,我在这里做的简单判断是为了让大家更容易理解。
最后通过重新显示Layer1的innerHTML值来显示新的排序内容。

(2)文本中:

select="team"
在我这里它是 sortField[1],但你在做的时候可能就会更改。
那么你就一定要计算准确可错不得哦,不然就找到别家去了!
我提供一个常用的方法:在代码里你可以用循环来判断是否为你需要的节点。


另外说一点:
XML对大小写的要求极其严格。所以你的书写不规范的话,它可是会感冒的呀!


后记:
大家熟悉动态排序和动态查询的完成思路后会发现,其实我们的实现手法很简单。
就是修改某一个数值,然后重新显示。
在动态分页的功能中我们依然是按照这个思路去完成的。  


--  作者:小鞋子
--  发布时间:2/19/2004 9:16:00 AM

--  
(3):动态分页
原作者:車仔

动机:
为了方便用户查看大批量数据,我们会用到动态分页,因此分页功能是我们在网站上见过的最普遍也是最常用的一个功能模块了。而以往的信息分页都是连接到数据库的,每一次点击都必须要后台数据库的支持。这样不但服务器的负担加重,而且严重的影响用户浏览的速度.
试想,如果把分页的功能放到客户端,那会产生什么样的效果呢?呵呵,看看下面的设计吧! 。

材料:
XML卷之动态分页
有2个文件:pages.xml 和 pages.xsl

作用:
把分页的功能放到客户端。在不刷新页面的情况下对数据进行过滤筛选,有效的提高浏览数据功能的效率。  
效果:
浏览这里  
代码:
pages.xml
<?xml version="1.0" encoding="gb2312" ?>
<?xml-stylesheet type="text/xsl" href="pages.xsl" ?>
<BlueIdea>
  <team>
    <blue_ID>1</blue_ID>
    <blue_name>Sailflying</blue_name>
    <blue_text>一个简单的分页</blue_text>
    <blue_time>2002-1-11 17:35:33</blue_time>
    <blue_class>XML专题</blue_class>
  </team>
  <team>
    <blue_ID>2</blue_ID>
    <blue_name>flyingbird</blue_name>
    <blue_text>嫁给你,是要你疼的</blue_text>
    <blue_time>2001-09-06 12:45:51</blue_time>
    <blue_class>灌水精华</blue_class>
  </team>
  <team>
    <blue_ID>3</blue_ID>
    <blue_name>苛子</blue_name>
    <blue_text>正则表达式在UBB论坛中的应用</blue_text>
    <blue_time>2001-11-23 21:02:16</blue_time>
    <blue_class>Web 编程精华</blue_class>
  </team>
  <team>
    <blue_ID>4</blue_ID>
    <blue_name>太乙郎</blue_name>
    <blue_text>年末经典分舵聚会完全手册 v0.1</blue_text>
    <blue_time>2000-12-08 10:22:48</blue_time>
    <blue_class>论坛灌水区</blue_class>
  </team>
  <team>
    <blue_ID>5</blue_ID>
    <blue_name>mmkk</blue_name>
    <blue_text>Asp错误信息总汇</blue_text>
    <blue_time>2001-10-13 16:39:05</blue_time>
    <blue_class>javascript脚本</blue_class>
  </team>
</BlueIdea>

pages.xsl
<?xml version="1.0" encoding="gb2312" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<html>
<head>
<title> XML卷之实战锦囊(3):动态分页</title>
<style>
body,BlueIdea,team,blue_ID,blue_name,blue_text,blue_time,blue_class{ font: 12px "宋体", "Arial", "Times New Roman"; }
table { font-size: 12px; border: 0px double; border-color: #99CC99 #99CC99 #CCCCCC #CCCCCC; cellpadding:3;cellspacing:3; bgcolor:#eeeeee; text-decoration: blink}
span { font-size: 12px; color: red; }
.keybutton { cursor:hand; font-size: 12px; color: #003300; background: #ffffff; border: 0px solid;}
</style>
<script>
<xsl:comment>
<![CDATA[
var OnePageNum=2;
var PageNum=1;
var XMLPageNum=1;
function pages(Num)
{
stylesheet=document.XSLDocument;
source=document.XMLDocument;
nodes=source.documentElement.childNodes;
len=nodes.length;
for(i=1;i<=(len/OnePageNum);i++);
XMLPageNum=i;
var firstNum=0;
var lastNume=0;

if (Num=="first") {PageNum=1;}
if (Num=="previous") {if (PageNum>1) PageNum -=1;}
if (Num=="next") {if (PageNum<XMLPageNum) PageNum +=1;}
if (Num=="last") {PageNum =XMLPageNum;}

sortField=document.XSLDocument.selectSingleNode("//@expr");
firstNum=OnePageNum*(PageNum-1)+1;
lastNum=OnePageNum*(PageNum-1)+OnePageNum;
text="childnumber(this)>="+firstNum+" & childnumber(this)<="+lastNum;
sortField.value=text;
Layer1.innerHTML=source.documentElement.transformNode(stylesheet);
}
]]>
</xsl:comment>
</script>
</head>

<body>
<p align="center"><span>XML卷之实战锦囊(3):动态分页</span></p>
<table align="center" width="500" >
<tr>
<td>
<button id="cmdfirstPage" class="keybutton" onclick="pages('first');" >首页</button>
<button id="cmdpreviousPage" class="keybutton" onclick="pages('previous');" >上一页</button>
<button id="cmdnextPage" class="keybutton" onclick="pages('next');">下一页</button>
<button id="cmdlastPage" class="keybutton" onclick="pages('last');">尾页</button>
</td>
</tr>
</table>
<div id="Layer1" name="Layer1"> <xsl:apply-templates select="BlueIdea" /></div>
</body>

</html>
</xsl:template>
<xsl:template match="BlueIdea">
<table width="500" border="1" align="center" cellpadding="1" cellspacing="1" bordercolordark="#ffffff" bordercolorlight="#ADAAAD">
<tr bgcolor="#FFCC99" align="center">
<td>编号</td>
<td>姓名</td>
<td>主题</td>
<td>发表时间</td>
<td>归类</td>
</tr>
<xsl:apply-templates select="team" order-by="blue_ID"/>
</table>
</xsl:template>
<xsl:template match="team">
<xsl:if expr="childnumber(this)&gt;=1 &amp; childnumber(this)&lt;=2 ">
<tr align="center">
<xsl:apply-templates select="blue_ID" />
<xsl:apply-templates select="blue_name" />
<xsl:apply-templates select="blue_text" />
<xsl:apply-templates select="blue_time" />
<xsl:apply-templates select="blue_class" />
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="blue_ID">
<td bgcolor="#eeeeee">
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_name">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_text">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_time">
<td>
<xsl:value-of />
</td>
</xsl:template>
<xsl:template match="blue_class">
<td>
<xsl:value-of />
</td>
</xsl:template>
</xsl:stylesheet>


讲解:
1)search.xml 是数据文件,相信大家都不会有问题。
2)search.xsl 是格式文件,有几个地方要注意。

(1)脚本中:

nodes=source.documentElement.childNodes;
作用是:找到所有的节点。nodes.length就是符合条件的总节点数

sortField=document.XSLDocument.selectSingleNode("//@expr");
作用是:找到有属性为expr的第一个节点,因此它对应的节点就是
<xsl:if expr="childnumber(this)&gt;=1 &amp; childnumber(this)&lt;=2 ">
因此在初次onLoad的时候expr的value值是
childnumber(this)<=1 & childnumber(this)>=2
关于 &gt; &lt; 大家可能熟悉多了。那&amp;是什么呢? 它就是“与”了.
大家可以在XML的书中找到其它的一些。

参数说明:
OnePageNum:每页显示的数据数
PageNum:当前页数
XMLPageNum:总页数
firstNum:当前页的第一条数据值
lastNum:当前页的最后一条数据值


(2)文本中:

<xsl:if expr="childnumber(this)&gt;=1 &amp; childnumber(this)&lt;=2 ">
在分页中我们需要输出合适的数据,,因此我们用一个 if 判断条件来控制。
在初始的时候我们要求只输出最前的两个节点的数值。

childnumber(this)
作用:返回当前节点在它的上级节点列表中的编号,列表中的第一个节点默认编号为1。
在分页中我们就是根据节点的编号来判断它属于第几页。
expr
不知道大家发现没有,前两次我们用到的都是 test ,可这个我们用的却是expr。
它们之间有一定的区别,用法也不相同。
expr ── 脚本语言表达式,计算结果为"真"或"假";如果结果为"真",且通过test,则在输出中显示其中内容(可省略此项属性)。
test ── 源数据测试条件。

<button id="cmdfirstPage" class="keybutton" onclick="pages('first');" >首页</button>
作用是让数据回到最前一页。其它按钮的作用类似。

补充一点: XML例子文件的使用方法

1)将每个例子里的两个文件按照文件名分别保存。
2)用浏览器浏览XML文件即可。这是你会看到效果,应该不错吧!  


后记:
呵呵,可以增加动态排序后,再分页的功能。再把列表数变为可设置。发挥你的思维,让这些功能更加完美。大家可以研究出更好的方法来实现分页功能。互相探讨,不亦乐乎!  


--  作者:小鞋子
--  发布时间:2/19/2004 9:17:00 AM

--  
(4):选单连动
原作者:車仔
动机:
现在我们做个在IE里应用XML的一个小例子:解决双下拉选单的连动问题。大家最常见的可能就是选取省份后改变城市选项的例子了,那我们就来尝试着用XML来完成吧。

以前介绍的一些功能我是直接用XML+XSL文件来完成的,大家可能还不是很熟悉它的用法,所以我这次就用HMTL+XML来做,希望能够让大家更清楚的了解--“XML原来可以如此简单!”:)


材料:
XML卷之选单连动
有2个文件:Citys.xml 和 CitySelect.htm

作用:
选择省份后可以自动显示相对应的城市,这样方便用户,有效的提高数据互动,让自己的页面更加绚丽多彩。  
效果:
浏览这里  
代码:
Citys.xml
<?xml version="1.0" encoding="gb2312"?>
<China>
  <State id="1" name="江西">
    <City>九江</City>
    <City>南昌</City>
    <City>庐山</City>
    <City>景德镇</City>
  </State>
  <State id="2" name="北京">
    <City>北京西</City>
    <City>居庸关</City>
    <City>清华园</City>
    <City>周口店</City>
  </State>
  <State id="3" name="福建">
    <City>福州</City>
    <City>厦门</City>
    <City>漳州</City>
  </State>
  <State id="4" name="甘肃">
    <City>兰州</City>
    <City>洛门</City>
    <City>嘉峪关</City>
  </State>
  <State id="5" name="广东">
    <City>广州</City>
    <City>深圳</City>
    <City>东莞</City>
    <City>石牌</City>
  </State>
  <State id="6" name="安徽">
    <City>合肥</City>
    <City>黄山</City>
    <City>九龙岗</City>
    <City>马鞍山</City>
  </State>
</China>

CitySelect.htm

自定义函数:ChooseState
(读取XML数据中的省的名称,并增加到SelState的下拉列表中)

function ChooseState()
{
  var source;
  var sourceName = "Citys.xml";
  var source = new ActiveXObject('Microsoft.XMLDOM');   //创建一个 MSXML解析器实例
  source.async = false;
  source.load(sourceName);   //装入XML文档
  root = source.documentElement;   //设置文档元素为根节点元素
  sortField=root.selectNodes("//@name");   //搜索属性中含有name的所有节点
  for(var i=0;i<sortField.length;++i)   //增加省份名称到下拉列表
  {
    var oOption = document.createElement('OPTION');
    oOption.text = " "+sortField[i].text+" ";
    oOption.value = sortField[i].text;
     form1.SelState.options.add(oOption);
  }
   ChooseCity();
}

自定义函数:ChooseCity
(根据当前选定的省名来读取XML数据中的对应城市名称,并增加到SelCity 的下拉列表中)
function ChooseCity()
{
  x=form1.SelState.selectedIndex;   //读取省份下拉框的当前选项
  y=form1.SelState.options[x].value;
  sortField=root.selectNodes("//State[@name='"+y+"']/City&q uot;);   //搜索name属性值等于
参数y的State节点下的所有city节点
  for(var i=form1.SelCity.options.length-1;i>=0;--i)   //撤消原来的列表项
  {
    form1.SelCity.options.remove(i)
  }
  for(var i=0;i<sortField.length;++i)   //增加城市名称到下拉列表
  {
    var oOption = document.createElement('OPTION');
    oOption.text = " "+sortField[i].text+" ";
    oOption.value = sortField[i].text;
    form1.SelCity.options.add(oOption);
  }
}

表单源码
<BODY onLoad="ChooseState()">
<FORM action="" method="post" id="form1" name="form1">
<SELECT name="SelState" id="SelState" onchange="ChooseCity()" >
</SELECT>
<SELECT name="SelCity" id="SelCity" >
</SELECT>
</FORM>
</BODY>

后记:
刚开始学XML的时候,我也有着和大家一样的迷惑 --- “XML我是学了,可究竟这XML应该怎么用呢?”这个问题阻难了我很久,很久......

因为电子商务和软件开发是我的专长,于是我觉得还是从身边最熟悉的开始做起吧。所以我将网站建设中最常用到的一些功能以XML的方式来完成。 你也一样可以的!


--  作者:小鞋子
--  发布时间:2/19/2004 9:18:00 AM

--  
(5):结构树图
原作者:車仔
动机:
最初想起做二叉树是因为需要做一个公司结构图。 以前的做法都是直接用图象软件画出来一个图片。很好看,但每次有变动后都需要重新画一个新的。 另一方面,网页上对线条的显示、布局相当局限。根据动态生成的数据进行排版、定位都相当困难, 而且在美观上也差强人意。 做了各种尝试以后,决定用XML+XSL作数据运算; 用VML来美化线条,用JAVASCRIPT来给对象定位。

材料:
XML卷之结构树图
有2个文件:flow2.xml 和 flow2.xsl  
效果:
浏览这里  
讲解:
二叉树思路(1)

<html xmlns:v="urn:schemas-microsoft-com:vml">
<STYLE>
v\:* { BEHAVIOR: url(#default#VML) }
</STYLE>
<v:group id="group1" name="group1" coordsize = "100,100">

</v:group>
以上这些都是VML的基本格式,我就不详细讲解了。

XML是树型结构,我们读取每个数据就需要对这个
XML数据树进行遍历。而递归运算是XSL优势之一。
我也是在用其它多种方法进行遍历运算失败后才
决定使用XSL的。

<FlowRoot>
<vcTitle>二叉树--结构图</vcTitle>
<Author>Sailflying</Author>
<Email>sailflying@163.net</Email>
<FlowNode>
<iProcess>1</iProcess>
<vcCourse>第一个节点</vcCourse>
<iNextYes>
<FlowNode>
<iProcess>2</iProcess>
<vcCourse>第二个节点</vcCourse>
<iNextYes>…</iNextYes>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextYes>
<iNextNo>
<FlowNode>
<iProcess>3</iProcess>
<vcCourse>第三个节点</vcCourse>
<iNextYes>…</iNextYes>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextNo>
</FlowNode>
</FlowRoot>


逻辑上很简单,当前节点(1)下面有两个子节点(2,3)。
只需要将节点2和节点3定位在节点1的左下方和右下方就可以了。
这里我将左右节点的连接线分别用了绿色和红色,方便显示。


前面我们说到了XSL的递归功能,为了更清楚的看到每一个详细的
显示步骤,只需要仿照下面的代码,加一个alert语句就可以了。

<xsl:template match="FlowNode">

<SCRIPT language="JavaScript1.2">

alert('逐步显示');

</SCRIPT>

</xsl:template>


看了上面的慢动作,是否能让大家了解到我的思路。


二叉树思路(2)
我的思路很简单:
(1)读取当前节点的资料,用VML生成一个新的对象。
给对象赋初始数值(如 name,id,style样式等)
(2)用脚本控制来给当前对象定位
(3)当前节点和它的父亲节点之间加箭头,线条。
(4)继续找当前节点的子节点,一直循环定位到结束。
也就是所有节点都遍历完毕,已经生成好了树。


<xsl:template match="FlowNode">

<xsl:apply-templates />

</xsl:template>
<xsl:template match="iNextYes">
<xsl:apply-templates select="./FlowNode" />
</xsl:template>

<xsl:template match="iNextNo">
<xsl:apply-templates select="./FlowNode" />
</xsl:template>

整个递归过程就是靠上面这三个模块(template)来完成的。
第一个template在匹配当前节点中每一个子节点的模板的时候
调用了后面两个template; 而后面两个template又在具体执行
的时候调用了第一个template ,这就相当于一个递归函数。

语法:

要依次匹配当前节点中的每个子节点的模板,应使用该元
素的基本形式 <xsl:apply-templates />。
否则,匹配的节点由 select 参数中 XPath 表达式的值决
定,如 <xsl:apply-templates select="./FlowNode" />

(1)和(2)的作用都是返回由 select 参数给出的表达式的字符串值。
他们的搜索条件相同,所以返回的值也一样。
只不过是使用的场合不同,他们的书写形式也就不一样。


(1) <xsl:value-of select="./iProcess/text()" />
(2) {./iProcess/text()}


这里定义了一些变量,节点的定位就是根据这些变量来调用运算公式的。

root_left //根的左边距=所有叶子的分配宽度(y*10) + 所有叶子的宽度(y*50) + 左边距基本值(10)
root_top //根的上边距=上边距基本值(10)
objOval //当前对象,是一个object
objOval_iProcess //当前对象的步骤值
objParentOval //当前对象的父节点,是一个object
objParentOval_iProcess //当前对象父节点的步骤值
objParent_name //当前对象父节点的名称
Leaf_left //当前对象的所有子节点中的左边叶子数
Leaf_right //当前对象的所有子节点中的右边叶子数
Leaf_sum //当前对象的所有子节点中叶子数

叶子:是指当前节点没有子节点


节点的定位公式:

(1) 当前节点是根节点

//根的位置
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//parseInt() 函数的作用是取整数值,如果不是则为NAN
//isNaN()函数的作用是判断parseInt取得的是否为整数


(2)当前节点是父节点的左边子节点

1)判断的条件是: 当前对象父节点的名称='iNextYes'

2)如果存在右边子叶子,则公式为:
当前节点的left=父节点的left - 当前节点的右边子叶子的总宽度- 当前节点的宽度

3)如果不存在右边子叶子,但存在左边子叶子,则公式为:
当前节点的left=父节点的left - 当前节点的左边子叶子的总宽度

4)如果当前节点本身就是叶子,则公式为:
当前节点的left=父节点的left - 当前节点的宽度

(3)当前节点是父节点的右边子节点

1)判断的条件是: 当前对象父节点的名称='iNextNo'

2)如果存在左边子叶子,则公式为:
当前节点的left=父节点的left + 当前节点的左边子叶子的总宽度 + 当前节点的宽度

3)如果不存在左边子叶子,但存在右边子叶子,则公式为:
当前节点的left=父节点的left + 当前节点的右边子叶子的总宽度

4)如果当前节点本身就是叶子,则公式为:
当前节点的left=父节点的left + 当前节点的宽度


(2)和(3)的公式都是得到当前节点的left,我们还需要得到当前节点的top
很简单的公式:当前节点的top=父节点的top + 偏移量(80)


二叉树思路(3)
连接线条的定位思路:
(1)找到当前节点和父节点的位置
(2)判断当前节点是父节点的左边子节点,还是右边子节点
(3)画线条


这里定义了一些变量。

objOval //当前节点,是一个object
objParentOval //当前对象的父节点,是一个object
objLine //当前线条,是一个object


线条的定位公式:


from="x1,y1" to="x2,y2" 是 VML 里定位线条的方式

当前节点是父节点的左边子节点,则公式为:
from = 父节点的left + 偏移量(15) , 父节点的top + 偏移量(32)
to = 父节点的left + 偏移量(30) , 父节点的top - 偏移量(2)

当前节点是父节点的右边子节点,则公式为:
from = 父节点的left + 偏移量(35) ,父节点的top + 偏移量(32)
to = 父节点的left + 偏移量(20) ,父节点的top - 偏移量(2)


我所能想到的也就这么多了。

如果只是单纯的做一个公司结构图的话,会更简单很多。
下面是赛扬的思路,我也是在他的基础上深入一点而已。

首先计算最下层节点个数,得出宽度,
然后应该根据节点的从属关系计算其上层节点位置,递归。
每一层级的节点要按从属关系先排序
首先设“基本值”=节点应向右偏移量
每个包含子节点的节点的left值等于它所拥有的节点所占宽度的一半加上基本值

后话:

最近不知为何,网络一直都不好。断线的时间比在线的时间多。
所以没对代码简化,其实,要完善的功能还有很多,比如:
需要加右键菜单
右键菜单内含新建节点、修改节点名称、改变关联关系等
在每一个节点上都可右键打开这个节点的右键菜单

讲解:
1)flow2.xml 是数据文件,相信大家都不会有问题。
2)flow2.xsl 是格式文件,有几个地方要注意。  
(1)脚本中:

(1) <xsl:value-of select="./iProcess/text()" /> ;
(2) {./iProcess/text()}

(1)和(2)的作用都是返回由 select 参数给出的表达式的字符串值。
他们的搜索条件相同,所以返回的值也一样。
只不过是使用的场合不同,他们的书写形式也就不一样。
<xsl:apply-templates select="team" order-by="blue_ID"/>
比如我们想生成以下代码
<div 名称=“参数值”>内容</div>


我们假设名称为“name”,参数值为XML数据中当前节点下面的子节点book的值


第一种写法是先加属性名称,再加参数值
<div>
<xsl:attribute name="name">
<xsl:value-of select="./book/text()"/> </xsl:attribute>
内容
</div>

第二种写法是直接加属性名称和参数值
<div name="{./book/text()}">内容</div>

具体的使用你可以看我写的代码中的例子。

XSL在正式的 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 的标准里

<xsl:value-of select="./book/text()"/>
作用是:只是把他的文本值写出来,而
<xsl:value-of select="./book"/>
是把他的文本值和他的所有子节点的内容显示出来。
大家可以试验一下,输出一个有子节点的,一个无子节点的
看看显示的结果是否相同。


(2)需要注意:

IE5 不支持 <tag att="{xpath}">
要用
<tag><xsl:attribute name="att"><xsl:value-of select="xpath"></xsl:attribute>

命名空间要用
xmlns:xsl="http://www.w3.org/TR/WD-xsl"

<?xml version="1.0" encoding="gb2312" ?>
另外说一点:
在大多的XML教科书中所显示的代码中很少会加上encoding="gb2312" ,
因此我们在XML中用到中文的时候会报错,原因就是没有写这个申明。


后记:
这里说的是一种思路。如果触类旁通,自然能够派上用场。  


--  作者:阳光小虾
--  发布时间:2/19/2004 1:10:00 PM

--  
不错,不错,小鞋子,这些方法你都测试过可行性了么?
--  作者:小鞋子
--  发布时间:2/19/2004 4:03:00 PM

--  
可行.
--  作者:阳光小虾
--  发布时间:2/19/2004 5:07:00 PM

--  
太好了,四个方法哦。谢谢。下载中。。。
--  作者:zhen4455
--  发布时间:2/22/2004 9:30:00 AM

--  
我有点疑问??:sortField.value=x;
能不能讲讲这个是怎么回事吗?我找了很多资料都没找到节点还有value这个属性。<xsl:apply-templates select="team" order-by="blue_ID"/>
这个order-by是不是参数啊,我也没找到相关资料。
我对这方面的东西是刚研究,,经验不足,请多指教,谢谢。请尽快回复。

--  作者:wwwsniper
--  发布时间:3/11/2004 9:25:00 AM

--  
OK.新来的,先收集一下。
--  作者:lisa
--  发布时间:3/11/2004 11:31:00 AM

--  
我要试试^_^
--  作者:车仔
--  发布时间:3/23/2004 1:04:00 AM

--  
以下是引用zhen4455在2004-2-22 9:30:26的发言:
我有点疑问??:sortField.value=x;
能不能讲讲这个是怎么回事吗?我找了很多资料都没找到节点还有value这个属性。<xsl:apply-templates select="team" order-by="blue_ID"/>
这个order-by是不是参数啊,我也没找到相关资料。
我对这方面的东西是刚研究,,经验不足,请多指教,谢谢。请尽快回复。


这个例子用的不是最新的xsl标准
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">


order-by 是 数据排序的方式,有点想mssql里的查询语句

sortField=document.XSLDocument.selectSingleNode("//@order-by");
作用是:找到有属性为order-by的第一个节点,因此它对应的节点就是
<xsl:apply-templates select="team" order-by="blue_ID"/>
因此在初次onLoad的时候order-by的value值是blue_ID。
而我们就是通过重新定义order-by的value值来达到排序的目的。


--  作者:XWford
--  发布时间:3/23/2004 1:29:00 PM

--  
好帖,
才学的XML~~
虽并没 完全看懂,
收藏了 ,先
--  作者:小鞋子
--  发布时间:3/23/2004 1:30:00 PM

--  
以下是引用车仔在2004-3-23 1:04:49的发言:
[quote]以下是引用zhen4455在2004-2-22 9:30:26的发言:
  我有点疑问??:sortField.value=x;
  能不能讲讲这个是怎么回事吗?我找了很多资料都没找到节点还有value这个属性。<xsl:apply-templates select="team" order-by="blue_ID"/>
  这个order-by是不是参数啊,我也没找到相关资料。
  我对这方面的东西是刚研究,,经验不足,请多指教,谢谢。请尽快回复。
  
[/quote]

这个例子用的不是最新的xsl标准
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">


order-by 是 数据排序的方式,有点想mssql里的查询语句

sortField=document.XSLDocument.selectSingleNode("//@order-by");
作用是:找到有属性为order-by的第一个节点,因此它对应的节点就是
<xsl:apply-templates select="team" order-by="blue_ID"/>
因此在初次onLoad的时候order-by的value值是blue_ID。
而我们就是通过重新定义order-by的value值来达到排序的目的。



车车来了...呵...


--  作者:人间流星
--  发布时间:3/25/2004 1:35:00 PM

--  
都是这些啊,有没有不能显示XML的具体路径的啊?
--  作者:changliu
--  发布时间:3/31/2004 9:28:00 AM

--  
好感激你,让我大悟

--  作者:hong0119
--  发布时间:4/8/2004 9:03:00 AM

--  
真的很不错,谢谢提供。
--  作者:guile
--  发布时间:4/14/2004 7:50:00 PM

--  
俺也新来的,收集一下~
--  作者:victoryn
--  发布时间:4/18/2004 1:28:00 AM

--  
无法显示 XML 页。
使用 XSL 样式表无法查看 XML 输入。请更正错误然后单击 刷新按钮,或以后重试。


--------------------------------------------------------------------------------

文档的最上层无效。处理资源 'file://D:\xml\paixu.xsl' 时出错。第 1 行,位置: 1

paixu.xsl
^
这是什么意思啊。


--  作者:victoryn
--  发布时间:4/18/2004 1:31:00 AM

--  
无法显示 XML 页。
使用 XSL 样式表无法查看 XML 输入。请更正错误然后单击 刷新按钮,或以后重试。


--------------------------------------------------------------------------------

文档的最上层无效。处理资源 'file://D:\xml\paixu.xsl' 时出错。第 1 行,位置: 1

paixu.xsl 这是什么意思啊?谢谢
^


--  作者:huting
--  发布时间:4/19/2004 2:14:00 PM

--  
感谢!这段时间我正是缺这个的详细,
努力吧,谢谢你对大家提供的资料,
我不久也能为奋战在xml战壕的兄弟服务了
--  作者:cdcloudy
--  发布时间:5/7/2004 2:13:00 PM

--  
xx :)
--  作者:coundy
--  发布时间:5/9/2004 10:13:00 AM

--  
很不错,谢谢
--  作者:kxlin
--  发布时间:5/17/2004 4:54:00 PM

--  
太长拉,希望整理提供下载,谢谢!
--  作者:hanhan27
--  发布时间:9/27/2004 5:03:00 PM

--  

--  作者:ttuhappy
--  发布时间:4/9/2005 11:41:00 AM

--  
好文章,收藏
--  作者:rjsheng
--  发布时间:4/23/2005 4:29:00 PM

--  
下载  太好了
--  作者:chenshijun
--  发布时间:6/22/2005 9:01:00 PM

--  
谢谢,努力学习中
--  作者:寒冰008
--  发布时间:9/22/2005 3:44:00 PM

--  
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

与 xmlns:w="http://www.w3.org/TR/WD-xsl" 冲突,该怎么解决呢?


--  作者:271954142
--  发布时间:10/10/2005 8:33:00 PM

--  
刚学的咯,有点看不懂咯

--  作者:rabit
--  发布时间:11/10/2005 4:30:00 PM

--  
谢谢楼主,看来你不止會一點點XML.和ASP.以及FLASH,别太谦虚哦
--  作者:davidwang1207
--  发布时间:11/17/2005 8:50:00 PM

--  

--  作者:xinq
--  发布时间:11/22/2005 10:06:00 AM

--  
谢谢分享
--  作者:xinq
--  发布时间:11/22/2005 10:07:00 AM

--  
谢谢分享
--  作者:zhumoo
--  发布时间:3/20/2006 4:05:00 PM

--  
收藏
--  作者:Q~Y~Y
--  发布时间:3/21/2006 11:36:00 AM

--  
呵呵,收集!!
--  作者:2140265
--  发布时间:3/22/2006 1:57:00 PM

--  
<!-- This is an XML document that could be used as an email template. -->
<!ELEMENT EMAIL (TO , FROM, CC*, BCC*, SUBJECT?, BODY?)>
<!ATTLIST EMAIL
LANGUAGE (Western|Greek|Latin|Universal) "Western"
ENCRYPTED CDATA #IMPLIED
PRIORITY (NORMAL|LOW|HIGH) "NORMAL">
<!ELEMENT TO (#PCDATA)>
<!ELEMENT FROM (#PCDATA)>
<!ELEMENT CC (#PCDATA)>
<!ELEMENT BCC (#PCDATA)>
<!ATTLIST BCC
HIDDEN CDATA #FIXED "TRUE">
<!ELEMENT SUBJECT (#PCDATA)>
<!ELEMENT BODY (#PCDATA)>



--  作者:2140265
--  发布时间:3/22/2006 2:02:00 PM

--  
利用MSXML解析XML文本(一)

--------------------------------------------------------------------------------
http://tech.sina.com.cn 2001/02/08 18:24 软件世界 胡朝晖
  一、引言

  当前Web上流行的剧本语言是以HTML为主的语言结构,HTML是一种标记语言,而不是一种编程语言,主要的标记是

针对显示,而不是针对文档内容本身结构的描述的。也就是说,机器本身是不能够解析它的内容的,所以就出现了XML

语言。XML (eXtensible Markup Language)语言是SGML语言的子集,它保留了SGML主要的使用功能,同时大大缩减了

SGML的复杂性。XML语言系统建立的目的就是使它不仅能够表示文档的内容,而且可以表示文档的结构,这样在同时能

够被人类理解的同时,也能够被机器所理解。XML要求遵循一定的严格的标准。XML分析程序比HTML浏览器更加要挑剔语

法和结构,XML要求正在创建的网页正确的使用语法和结构,而不是象HTML一样,通过浏览器推测文档中应该是什么东

西来实现HTML的显示,XML使得分析程序不论在性能还是稳定性方面都更容易实现。XML文档每次的分析结果都是一致的

,不象HTML,不同的浏览器可能对同一个HTML作出不同的分析和显示。

  同时因为分析程序不需要花时间重建不完整的文档,所以它们能比同类HTML能更有效地执行其任务。它们能全力以

赴地根据已经包含在文档中的那个树结构建造出相应的树来,而不用在信息流中的混合结构的基础上进行显示。XML标

准是对数据的处理应用,而不是只针对Web网页的。任何类型的应用都可以在分析程序的上面进行建造,浏览器只是XML

的一个小的组成部分。当然,浏览仍旧极其重要,因为它为XML工作人员提供用于阅读信息的友好工具。但对更大的项

目来说它就不过是一个显示窗口。因为XML具有严格的语法结构,所以我们甚至可以用XML来定义一个应用层的通讯协议

,比如互联网开放贸易协议(Internet Open Trading Protocol)就是用XML来定义的。从某种意义上说,以前我们用BNF

范式定义的一些协议和格式从原则上说都可以用XML来定义。实际上,如果我们有足够的耐心,我们完全可以用XML来定

义一个C++语言的规范。

  当然,XML允许大量HTML样式的形式自由的开发,但是它对规则的要求更加严格。XML主要有三个要素:DTD

(Document Type Declaration——文档类型声明)或XML Schema(XML大纲)、XSL(eXtensible Stylesheet Language——

可扩展样式语言)和XLink(eXtensible Link Language——可扩展链接语言)。DTD和XML大纲规定了XML文件的逻辑结构

,定义了XML文件中的元素、元素的属性以及元素和元素的属性之间的关系;Namespace(名域)实现统一的XML文档数据

表示以及数据的相互集成;XSL是用于规定XML文档呈现样式的语言,它使得数据与其表现形式相互独立,比如XSL能使

Web浏览器改变文档的表示法,例如数据的显示顺序的变化,不需要再与服务器进行通讯。通过改变样式表,同一个文

档可以显示得更大,或者经过折叠只显示外面得一层,或者可以变为打印得格式。而XLink将进一步扩展目前Web上已有

的简单链接。

利用MSXML解析XML文本(二)

--------------------------------------------------------------------------------
http://tech.sina.com.cn 2001/02/08 18:25 软件世界 胡朝晖
  二、实现XML解析的说明

  当然,从理论上说,根据XML的格式定义,我们可以自己编写一个XML的语法分析器,但是实际上微软已经给我们提

供了一个XML语法解析器,如果你安装了IE5.0以上版本的话,实际上你就已经安装了XML语法解析器。可以从微软站点

(www.microsoft.com)下载最新的MSXML的SDK和Parser文件。它是一个叫做MSXML.DLL的动态链接库,最新版本为msxml3

,实际上它是一个COM对象库,里面封装了所有进行XML解析所需要的所有必要的对象。因为COM是一种以二进制格式出

现的和语言无关的可重用对象。所以你可以用任何语言(比如VB,VC,DELPHI,C++ Builder甚至是剧本语言等等)对它

进行调用,在你的应用中实现对XML文档的解析。下面的关于XML文档对象模型的介绍是基于微软最新的msxml3为基础进

行的。

  三、XML文档对象(XML DOM)模型分析

  XML DOM对象提供了一个标准的方法来操作存储在XML文档中的信息,DOM应用编程接口(API)用来作为应用程序和

XML文档之间的桥梁。

  DOM可以认为是一个标准的结构体系用来连接文档和应用程序(也可以是剧本语言)。MSXML解析器允许你装载和创建

一个文档,收集文档的错误信息,得到和操作文档中的所有的信息和结构,并把文档保存在一个XML文件中。DOM提供给

用户一个接口来装载、到达和操作并序列化XML文档。DOM提供了对存储在内存中的XML文档的一个完全的表示,提供了

可以随机访问整个文档的方法。DOM允许应用程序根据MSXML解析器提供的逻辑结构来操作XML文档中的信息。利用MSXML

所提供的接口来操作XML。

  实际上MSXML解析器根据XML文档生成一个DOM树结构,它能够读XML文档并根据XML文档内容创建一个节点的逻辑结

构,文档本身被认为是一个包含了所有其他节点的节点。

  DOM使用户能够把文档看成是一个有结构的信息树,而不是简单的文本流。这样应用程序或者是剧本即使不知道XML

的语义细节也能够方便的操作该结构。DOM包含两个关键的抽象:一个树状的层次、另一个是用来表示文档内容和结构

的节点集合。树状层次包括了所有这些节点,节点本身也可以包含其他的节点。这样的好处是对于开发人员来说,他可

以通过这个层次结构来找到并修改相应的某一个节点的信息。DOM把节点看成是一个通常的对象,这样就有可能创建一

个剧本来装载一个文档,然后遍历所有的节点,显示感兴趣的节点的信息。注意节点可以有很多中具体的类型,比如元

素、属性和文本都可以认为是一个节点。

  微软的MSXML解析器读一个XML文档,然后把它的内容解析到一个抽象的信息容器中称为节点(NODES)。这些节点代

表文档的结构和内容,并允许应用程序来读和操作文档中的信息而不需要显示的知道XML的语义。在一个文档被解析以

后,它的节点能够在任何时候被浏览而不需要保持一定的顺序。

  对开发人员来说,最重要的编程对象是DOMDocument。DOMDocument对象通过暴露属性和方法来允许你浏览,查询和

修改XML文档的内容和结构,每一个接下来的对象暴露自己的属性和方法,这样你就能够收集关于对象实例的信息,操

作对象的值和结构,并导航到树的其他对象上去。

利用MSXML解析XML文本(三)

--------------------------------------------------------------------------------
http://tech.sina.com.cn 2001/02/08 18:27 软件世界 胡朝晖
  MSXML.DLL所包括的主要的COM接口有:

  (1)DOMDocument

  DOMDocument对象是XML DOM的基础,你可以利用它所暴露的属性和方法来允许你浏览、查询和修改XML文档的内容

和结构。DOMDocument表示了树的顶层节点。它实现了DOM文档的所有的基本的方法并且提供了额外的成员函数来支持

XSL和XSLT。它创建了一个文档对象,所有其他的对象都可以从这个文档对象中得到和创建。

  (2)IXMLDOMNode

  IXMLDOMNode是文档对象模型(DOM)中的基本的对象,元素,属性,注释,过程指令和其他的文档组件都可以认为是

IXMLDOMNode,事实上,DOMDocument对象本身也是一个IXMLDOMNode对象。

  (3)IXMLDOMNodeList

  IXMLDOMNodeList实际上是一个节点(Node)对象的集合,节点的增加、删除和变化都可以在集合中立刻反映出来,

可以通过“for...next”结构来遍历所有的节点。

  (4)IXMLDOMParseError

  IXMLDOMParseError接口用来返回在解析过程中所出现的详细的信息,包括错误号,行号,字符位置和文本描述。

  下面主要描述一个DOMDocument对象的创建过程,这里我们用VC描述创建一个文档对象的过程。

  HRESULT hr;

  IXMLDomDocument* pXMLDoc;

  IXMLDOMNode* pXDN;

  Hr=CoInitialize(NULL); //COM的初始化

  //得到关于IXMLDOMDocument接口的指针pXMLDOC。

  hr=CoCreateInstance(CLSID_DOMDocument,NULL,CLSCTX_INPPROC_SERVER,

  IID_IXMLDOMDocument,(void**)&pXMLDoc);

  //得到关于IXMLDOMNode接口的指针pXDN。

  hr=pXMLDoc->QueryInterface(IID_IXMLDOMNode,(void**)&pXDN);

  在MSXML解析器使用过程中,我们可以使用文档中的createElement方法来创建一个节点装载和保存XML文件。通过

load或者是loadXML方法可以从一个指定的URL来装载一个XML文档。Load(LoadXML)方法带有两个参数:第一个参数

xmlSource表示需要被解析的文档,第二个参数isSuccessful表示文档装载是否成功。Save方法是用来把文档保存到一

个指定的位置。Save方法有一个参数destination用来表示需要保存的对象的类型,对象可以是一个文件,一个ASP

Response方法,一个XML文档对象,或者是一个能够支持持久保存(persistence)的客户对象。下面是save方法使用的一

个简单的例子(具体程序请参见http://www.swm.com.cn/swm/200101/利用MSXML解析XML文本)。

  同时,在解析过程中,我们需要得到和设置解析标志。利用不同的解析标志,我们可能以不同的方法来解析一个

XML文档。XML标准允许解析器验证或者不验证文档,允许不验证文档的解析过程跳过对外部资源的提取。另外,你可能

设置标志来表明你是否要从文档中移去多余的空格。

  为了达到这个目的,DOMDocument对象暴露了下面几个属性,允许用户在运行的时候改变解析器的行为:

  (1)Async(相对于C++是两个方法,分别为get_async和put_async)

  (2)ValidateOnparse (相对于C++是两个方法,分别为get_validateOnParse和 put_validateOnParse)

  (3)ResolveExternals(相对于C++是两个方法,分别为get_ ResolveExternals和put_ ResolveExternals)

  (4)PersercveWhiteSpace(相对于C++是两个方法,分别为get_ PersercveWhiteSpace和put_

PersercveWhiteSpace)

  每一个属性可以接受或者返回一个Boolean值。缺省的,anync,validateOnParse,resolveExternals的值为TRUE,

perserveWhiteSpace的值跟XML文档的设置有关,如果XML文档中设置了xml:space属性的话,该值为FALSE。

  同时在文档解析过程中可以收集一些和文档信息的信息,实际上在文档解析过程中可以得到以下的信息:

  (1)doctype(文档类型):实际上是和用来定义文档格式的DTD文件。如果XML文档没有相关的DTD文档的话,它就返

回NULL。

  (2)implementation(实现):表示该文档的实现,实际上就是用来指出当前文档所支持的XML的版本。

  (3)parseError(解析错误):在解析过程中最后所发生的错误。

  (4)readyState(状态信息):表示XML文档的状态信息,readyState对于异步使用微软的XML解析器来说的重要作用

是提高了性能,当异步装载XML文档的时候,你的程序可能需要检查解析的状态,MSXML提供了四个状态,分别为正在状

态,已经状态,正在解析和解析完成。

  (5)url(统一资源定位):关于正在被装载和解析的XML文档的URL的情况。注意如果该文档是在内存中建立的话,这

个属性返回NULL值。

  在得到文档树结构以后,我们可以操作树中的每一个节点,可以通过两个方法得到树中的节点,分别为nodeFromID

和getElementsByTagName。

  nodeFromID包括两个参数,第一个参数idString用来表示ID值,第二个参数node返回指向和该ID相匹配的NODE节点

的接口指针。注意根据XML的技术规定,每一个XML文档中的ID值必须是唯一的而且一个元素(element)仅且只能和一个

ID相关联。

  getElementsByTagName方法有两个参数,第一个参数tagName表示需要查找的元素(Element)的名称,如果tagName

为“*”的话返回文档中所有的元素(Element)。第二个参数为resultList,它实际是指向接口IXMLDOMNodeList的指针,

用来返回和tagName(标签名字)相关的所有的Node的集合。


利用MSXML解析XML文本(四)

--------------------------------------------------------------------------------
http://tech.sina.com.cn 2001/02/08 18:29 软件世界 胡朝晖
  下面是一个简单的例子

  下面是save方法使用的一个简单的例子:

  BOOL DOMDocSaveLocation()

  {

  BOOL bResult = FALSE;

  IXMLDOMDocument *pIXMLDOMDocument = NULL;

  HRESULT hr;


  try

  {

  _variant_t varString = _T("D:\\sample.xml");

  // 这里需要创建一个DOMDocument对象和装载XML文档,代码省略.

  hr = pIXMLDOMDocument->save(varString); //保存文档到D:\\sample.xml中去。

  if(SUCCEEDED(hr))

  bResult = TRUE;

  }

  catch(...)

  {

  DisplayErrorToUser();

  // 这里需要释放对IXMLDOMDocument接口的引用,代码省略。

  }

  return bResult;

  }


  例子2

  IXMLDOMDocument *pIXMLDOMDocument = NULL;

  wstring strFindText (_T("author"));

  IXMLDOMNodeList *pIDOMNodeList = NULL;

  IXMLDOMNode *pIDOMNode = NULL;

  long value;

  BSTR bstrItemText;

  HRESULT hr;

  try

  {

  // 创建一个DOMDocument文档对象,并装载具体文档,相关代码省略。

  //下面的代码用来得到一个和标签名称author相关的所有的节点集合

  hr = pIXMLDOMDocument->getElementsByTagName(

  (TCHAR*)strFindText.data(), &pIDOMNodeList);

  SUCCEEDED(hr) ? 0 : throw hr;

  //是否正确的得到了指向IDOMNodeList的指针。

  hr = pIDOMNodeList->get_length(&value); //得到所包含的NODE节点的个数

  if(SUCCEEDED(hr))

  {

  pIDOMNodeList->reset();

  for(int ii = 0; ii < value; ii++)

  {

  //得到具体的一个NODE节点

  pIDOMNodeList->get_item(ii, &pIDOMNode);

  if(pIDOMNode )

  {

  pIDOMNode->get_text(&bstrItemText); //得到该节点相关的文本信息

  ::MessageBox(NULL, bstrItemText,strFindText.data(), MB_OK);

  pIDOMNode->Release();

  pIDOMNode = NULL;

  }

  }

  }

  pIDOMNodeList->Release();

  pIDOMNodeList = NULL;

  }

  catch(...)

  {

  if(pIDOMNodeList)

  pIDOMNodeList->Release();

  if(pIDOMNode)

  pIDOMNode->Release();

  DisplayErrorToUser();

  }


  简单的实例程序

  #include < atlbase.h>

  //下面的.h文件是在安装了最新的XML Parser以后所包含的.h文件。

  #include "C:\Program Files\Microsoft XML Parser SDK\inc\msxml2.h"

  #include < iostream>

  void main()

  {

  // 初始化COM接口

  CoInitialize(NULL);

  //在程序中,我们假定我们装载的XML文件名称为xmldata.xml,它缺省的和可执行文

  //件在同一个目录中。该文件的内容如下:

  // < ?xml version="1.0"?>

  // < xmldata>

  // < xmlnode />

  // < xmltext>Hello, World!< / xmltext>

  // < /xmldata>

  //

  //程序将寻找名为“xmlnode”的节点,然后插入一个新的名称为“xmlchildnode”的

  //节点,然后它去寻找一个名为“xmltest”的节点,然后提取包含在节点中的文本并显

  //示它。最后它把新的改变过的XML文档保存在名称为“updatexml.xml”的文档中。

  try {

  // 通过智能指针创建一个解析器的实例。

  CComPtr< IXMLDOMDocument> spXMLDOM;

  HRESULT hr = spXMLDOM.CoCreateInstance(__uuidof(DOMDocument));

  if ( FAILED(hr) ) throw "不能创建XML Parser对象";

  if ( spXMLDOM.p == NULL ) throw "不能创建XML Parser对象";


  // 如果对象创建成功的话,就开始装载XML文档

  VARIANT_BOOL bSuccess = false;

  hr = spXMLDOM->load(CComVariant(L"xmldata.xml"),&bSuccess);

  if ( FAILED(hr) ) throw "不能够在解析器中装载XML文档";

  if ( !bSuccess ) throw "不能够在解析器中装载XML文档";

  // 检查并搜索"xmldata/xmlnode"

  CComBSTR bstrSS(L"xmldata/xmlnode");

  CComPtr< IXMLDOMNode> spXMLNode;

  //用接口IXMLDOMDocument的方法selectSingleNode方法定位该节点

  hr = spXMLDOM->selectSingleNode(bstrSS,&spXMLNode);

  if ( FAILED(hr) ) throw "不能在XML节点中定位'xmlnode' ";

  if ( spXMLNode.p == NULL ) throw "不能在XML节点中定位'xmlnode' ";

  //DOM对象“spXMLNode”现在包含了XML节点< xmlnode>,所以我们可以在

  //它下面创建一个子节点并把找到的该节点作为它的父节点。

  CComPtr< IXMLDOMNode> spXMLChildNode;

  //用接口IXMLDOMDocument的方法createNode方法创建一个新节点。

  hr = spXMLDOM->createNode(

  CComVariant(NODE_ELEMENT),

  CComBSTR("xmlchildnode"),

  NULL,&spXMLChildNode);

  if ( FAILED(hr) ) throw "不能创建'xmlchildnode' 节点";

  if ( spXMLChildNode.p == NULL )

  throw "不能创建'xmlchildnode' 节点";

  //添加新节点到spXMLNode节点下去。

  CComPtr< IXMLDOMNode> spInsertedNode;

  hr = spXMLNode->appendChild(spXMLChildNode,&spInsertedNode);

  if ( FAILED(hr) ) throw "不能创建'xmlchildnode' 节点";

  if ( spInsertedNode.p == NULL ) throw "不能移动'xmlchildnode' 节点";

  //对新节点添加属性。

  CComQIPtr< IXMLDOMElement> spXMLChildElement;

  spXMLChildElement = spInsertedNode;

  if ( spXMLChildElement.p == NULL )

  throw "不能在XML元素接口中查询到'xmlchildnode' ";

  //设置新节点的属性

  hr = spXMLChildElement->setAttribute(CComBSTR(L"xml"),CComVariant(L"fun"));

  if ( FAILED(hr) ) throw "不能插入新的属性";

  //下面的程序段用来寻找一个节点并显示该节点的相关信息

  // 查找"xmldata/xmltext"节点

  spXMLNode = NULL; // 释放先前的节点

  bstrSS = L"xmldata/xmltext";

  hr = spXMLDOM->selectSingleNode(bstrSS,&spXMLNode);

  if ( FAILED(hr) ) throw "不能定位'xmltext'节点";

  if ( spXMLNode.p == NULL ) throw "不能定位'xmltext'节点";


  // 得到该节点包含的文本并显示它

  CComVariant varValue(VT_EMPTY);

  hr = spXMLNode->get_nodeTypedValue(&varValue);

  if ( FAILED(hr) ) throw "不能提取'xmltext'文本";

  if ( varValue.vt == VT_BSTR ) {

  // 显示结果,注意这里要把字符串从形式BSTR转化为ANSI

  USES_CONVERSION;

  LPTSTR lpstrMsg = W2T(varValue.bstrVal);

  std::cout < < lpstrMsg < < std::endl;

  } // if

  else {

  // 如果出现错误

  throw "不能提取'xmltext'文本";

  } // else


  //保存修改过的XML文档到指定的文档名

  hr = spXMLDOM->save(CComVariant("updatedxml.xml"));

  if ( FAILED(hr) ) throw "不能保存修改过的XML文档";

  std::cout < < "处理完成..." < < std::endl < < std::endl;

  } // try

  catch(char* lpstrErr) {

  // 出现错误

  std::cout < < lpstrErr < < std::endl < < std::endl;

  } // catch

  catch(...) {

  // 未知错误

  std::cout < < "未知错误..." < < std::endl < < std::endl;

  } // catch


  // 结束对COM的使用

  CoUninitialize();

  }


利用MSXML解析XML文本(五)

--------------------------------------------------------------------------------
http://tech.sina.com.cn 2001/02/08 18:30 软件世界 胡朝晖
  最后我们讨论一下如何来创建新的节点,实际上可以通过方法createNode来创建一个新的节点。CreateNode包括四

个参数,第一个参数Type表示要创建的节点的类型,第二个参数name表示新节点的nodeName的值,第三个参数

namespaceURI表示该节点相关的名字空间,第四个参数node表示新创建的节点。注意可以通过使用已经提供的类型

(Type),名称(name)和名字空间(nodeName)来创建一个节点。

  当一个节点被创建的时候,它实际上是在一个名字空间范围(如果已经提供了名字空间的话)内创建的。如果没有提

供名字空间的话,它实际上是在文档的名字空间范围内创建的。

  四、利用MSXML进行XML文档分析的简单实例

  为了说明如何在VC中使用XML DOM模型,这里我们显示了一个简单的实例程序(具体程序请参见

www.swm.com.cn/swm/200101/利用MSXML解析XML文本),是一个Console Application。下面是主要的程序代码,本代码

用来在一个XML文档中定位一个特殊的Node节点,并插入一个新的子节点。

  五、总结

  XML文档因为有着比HTML严格的多的语法要求,所以使用和编写一个XML解析器要比编写一个HTML的解析器要容易的

多。同时因为XML文档不仅可以标记文档的显示属性,更重要的是它标记了文档的结构和包含信息的特征,所以我们可

以方便的通过XML解析器来获取特定节点的信息并加以显示或修改,方便了用户对XML文档的操作和维护。同时我们需要

注意的是XML是一种开放的结构体系并不依赖于任何一家公司,所以开发基于XML的应用必然会得到绝大多数软件开发平

台的支持。另外,我们也可以看到,象微软这样的软件开发主流企业也把目光定位在基于XML+COM的体系上,无论是微

软的Office系列、Web服务器和浏览器还是数据库产品(SQL Server)都已经开始支持基于XML的应用。通过XML来定制应

用程序的前端,COM来实现具体的业务对象和数据库对象,使系统具有更加灵活的扩展性和维护性。



--  作者:zhangjl1213
--  发布时间:3/24/2006 6:37:00 PM

--  
谢拉帮结伙
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
500.000ms