濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > XML卷之實(shí)戰(zhàn)錦囊(5):結(jié)構(gòu)樹(shù)圖

XML卷之實(shí)戰(zhàn)錦囊(5):結(jié)構(gòu)樹(shù)圖

熱門(mén)標(biāo)簽:本地電話(huà)機(jī)器人 東營(yíng)電銷(xiāo) 高德地圖地圖標(biāo)注服務(wù)中心 微信地圖標(biāo)注合并了 南寧網(wǎng)絡(luò)外呼系統(tǒng)運(yùn)營(yíng)商 400電話(huà)辦理包年 如何修改多個(gè)百度地圖標(biāo)注 r語(yǔ)言數(shù)據(jù)可視化地圖標(biāo)注 隨州外呼調(diào)研系統(tǒng)

動(dòng)機(jī):
最初想起做二叉樹(shù)是因?yàn)樾枰鲆粋€(gè)公司結(jié)構(gòu)圖。 以前的做法都是直接用圖象軟件畫(huà)出來(lái)一個(gè)圖片。很好看,但每次有變動(dòng)后都需要重新畫(huà)一個(gè)新的。 另一方面,網(wǎng)頁(yè)上對(duì)線(xiàn)條的顯示、布局相當(dāng)局限。根據(jù)動(dòng)態(tài)生成的數(shù)據(jù)進(jìn)行排版、定位都相當(dāng)困難, 而且在美觀上也差強(qiáng)人意。 做了各種嘗試以后,決定用XML+XSL作數(shù)據(jù)運(yùn)算; 用VML來(lái)美化線(xiàn)條,用JAVASCRIPT來(lái)給對(duì)象定位。

材料:
XML卷之結(jié)構(gòu)樹(shù)圖
有2個(gè)文件:flow2.xml 和 flow2.xsl 
效果:
瀏覽這里 
講解:
二叉樹(shù)思路(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的基本格式,我就不詳細(xì)講解了。

 

XML是樹(shù)型結(jié)構(gòu),我們讀取每個(gè)數(shù)據(jù)就需要對(duì)這個(gè)
XML數(shù)據(jù)樹(shù)進(jìn)行遍歷。而遞歸運(yùn)算是XSL優(yōu)勢(shì)之一。
我也是在用其它多種方法進(jìn)行遍歷運(yùn)算失敗后才
決定使用XSL的。

 

FlowRoot>
vcTitle>二叉樹(shù)--結(jié)構(gòu)圖/vcTitle>
Author>Sailflying/Author>
Email>sailflying@163.net/Email>
FlowNode>
iProcess>1/iProcess>
vcCourse>第一個(gè)節(jié)點(diǎn)/vcCourse>
iNextYes>
FlowNode>
iProcess>2/iProcess>
vcCourse>第二個(gè)節(jié)點(diǎn)/vcCourse>
iNextYes>…/iNextYes>
iNextNo>…/iNextNo>
/FlowNode>
/iNextYes>
iNextNo>
FlowNode>
iProcess>3/iProcess>
vcCourse>第三個(gè)節(jié)點(diǎn)/vcCourse>
iNextYes>…/iNextYes>
iNextNo>…/iNextNo>
/FlowNode>
/iNextNo>
/FlowNode>
/FlowRoot>


邏輯上很簡(jiǎn)單,當(dāng)前節(jié)點(diǎn)(1)下面有兩個(gè)子節(jié)點(diǎn)(2,3)。
只需要將節(jié)點(diǎn)2和節(jié)點(diǎn)3定位在節(jié)點(diǎn)1的左下方和右下方就可以了。
這里我將左右節(jié)點(diǎn)的連接線(xiàn)分別用了綠色和紅色,方便顯示。


前面我們說(shuō)到了XSL的遞歸功能,為了更清楚的看到每一個(gè)詳細(xì)的
顯示步驟,只需要仿照下面的代碼,加一個(gè)alert語(yǔ)句就可以了。

 

xsl:template match="FlowNode">

SCRIPT language="JavaScript1.2">

alert('逐步顯示');

/SCRIPT>

/xsl:template>


看了上面的慢動(dòng)作,是否能讓大家了解到我的思路。

 


二叉樹(shù)思路(2)
我的思路很簡(jiǎn)單:
(1)讀取當(dāng)前節(jié)點(diǎn)的資料,用VML生成一個(gè)新的對(duì)象。
給對(duì)象賦初始數(shù)值(如 name,id,style樣式等)
(2)用腳本控制來(lái)給當(dāng)前對(duì)象定位
(3)當(dāng)前節(jié)點(diǎn)和它的父親節(jié)點(diǎn)之間加箭頭,線(xiàn)條。
(4)繼續(xù)找當(dāng)前節(jié)點(diǎn)的子節(jié)點(diǎn),一直循環(huán)定位到結(jié)束。
也就是所有節(jié)點(diǎn)都遍歷完畢,已經(jīng)生成好了樹(shù)。

 


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>

 

整個(gè)遞歸過(guò)程就是靠上面這三個(gè)模塊(template)來(lái)完成的。
第一個(gè)template在匹配當(dāng)前節(jié)點(diǎn)中每一個(gè)子節(jié)點(diǎn)的模板的時(shí)候
調(diào)用了后面兩個(gè)template; 而后面兩個(gè)template又在具體執(zhí)行
的時(shí)候調(diào)用了第一個(gè)template ,這就相當(dāng)于一個(gè)遞歸函數(shù)。

語(yǔ)法:

 

要依次匹配當(dāng)前節(jié)點(diǎn)中的每個(gè)子節(jié)點(diǎn)的模板,應(yīng)使用該元
素的基本形式 xsl:apply-templates />。
否則,匹配的節(jié)點(diǎn)由 select 參數(shù)中 XPath 表達(dá)式的值決
定,如 xsl:apply-templates select="./FlowNode" />

 

(1)和(2)的作用都是返回由 select 參數(shù)給出的表達(dá)式的字符串值。
他們的搜索條件相同,所以返回的值也一樣。
只不過(guò)是使用的場(chǎng)合不同,他們的書(shū)寫(xiě)形式也就不一樣。


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


這里定義了一些變量,節(jié)點(diǎn)的定位就是根據(jù)這些變量來(lái)調(diào)用運(yùn)算公式的。

 

root_left //根的左邊距=所有葉子的分配寬度(y*10) + 所有葉子的寬度(y*50) + 左邊距基本值(10)
root_top //根的上邊距=上邊距基本值(10)
objOval //當(dāng)前對(duì)象,是一個(gè)object
objOval_iProcess //當(dāng)前對(duì)象的步驟值
objParentOval //當(dāng)前對(duì)象的父節(jié)點(diǎn),是一個(gè)object
objParentOval_iProcess //當(dāng)前對(duì)象父節(jié)點(diǎn)的步驟值
objParent_name //當(dāng)前對(duì)象父節(jié)點(diǎn)的名稱(chēng)
Leaf_left //當(dāng)前對(duì)象的所有子節(jié)點(diǎn)中的左邊葉子數(shù)
Leaf_right //當(dāng)前對(duì)象的所有子節(jié)點(diǎn)中的右邊葉子數(shù)
Leaf_sum //當(dāng)前對(duì)象的所有子節(jié)點(diǎn)中葉子數(shù)

葉子:是指當(dāng)前節(jié)點(diǎn)沒(méi)有子節(jié)點(diǎn)

 


節(jié)點(diǎn)的定位公式:

(1) 當(dāng)前節(jié)點(diǎn)是根節(jié)點(diǎn)

 

//根的位置
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//parseInt() 函數(shù)的作用是取整數(shù)值,如果不是則為NAN
//isNaN()函數(shù)的作用是判斷parseInt取得的是否為整數(shù)


(2)當(dāng)前節(jié)點(diǎn)是父節(jié)點(diǎn)的左邊子節(jié)點(diǎn)

 

1)判斷的條件是: 當(dāng)前對(duì)象父節(jié)點(diǎn)的名稱(chēng)='iNextYes'

2)如果存在右邊子葉子,則公式為:
當(dāng)前節(jié)點(diǎn)的left=父節(jié)點(diǎn)的left - 當(dāng)前節(jié)點(diǎn)的右邊子葉子的總寬度- 當(dāng)前節(jié)點(diǎn)的寬度

3)如果不存在右邊子葉子,但存在左邊子葉子,則公式為:
當(dāng)前節(jié)點(diǎn)的left=父節(jié)點(diǎn)的left - 當(dāng)前節(jié)點(diǎn)的左邊子葉子的總寬度

4)如果當(dāng)前節(jié)點(diǎn)本身就是葉子,則公式為:
當(dāng)前節(jié)點(diǎn)的left=父節(jié)點(diǎn)的left - 當(dāng)前節(jié)點(diǎn)的寬度

 

(3)當(dāng)前節(jié)點(diǎn)是父節(jié)點(diǎn)的右邊子節(jié)點(diǎn)

 

1)判斷的條件是: 當(dāng)前對(duì)象父節(jié)點(diǎn)的名稱(chēng)='iNextNo'

2)如果存在左邊子葉子,則公式為:
當(dāng)前節(jié)點(diǎn)的left=父節(jié)點(diǎn)的left + 當(dāng)前節(jié)點(diǎn)的左邊子葉子的總寬度 + 當(dāng)前節(jié)點(diǎn)的寬度

3)如果不存在左邊子葉子,但存在右邊子葉子,則公式為:
當(dāng)前節(jié)點(diǎn)的left=父節(jié)點(diǎn)的left + 當(dāng)前節(jié)點(diǎn)的右邊子葉子的總寬度

4)如果當(dāng)前節(jié)點(diǎn)本身就是葉子,則公式為:
當(dāng)前節(jié)點(diǎn)的left=父節(jié)點(diǎn)的left + 當(dāng)前節(jié)點(diǎn)的寬度

 


(2)和(3)的公式都是得到當(dāng)前節(jié)點(diǎn)的left,我們還需要得到當(dāng)前節(jié)點(diǎn)的top
很簡(jiǎn)單的公式:當(dāng)前節(jié)點(diǎn)的top=父節(jié)點(diǎn)的top + 偏移量(80)

 


二叉樹(shù)思路(3)
連接線(xiàn)條的定位思路:
(1)找到當(dāng)前節(jié)點(diǎn)和父節(jié)點(diǎn)的位置
(2)判斷當(dāng)前節(jié)點(diǎn)是父節(jié)點(diǎn)的左邊子節(jié)點(diǎn),還是右邊子節(jié)點(diǎn)
(3)畫(huà)線(xiàn)條


這里定義了一些變量。

 

objOval //當(dāng)前節(jié)點(diǎn),是一個(gè)object
objParentOval //當(dāng)前對(duì)象的父節(jié)點(diǎn),是一個(gè)object
objLine //當(dāng)前線(xiàn)條,是一個(gè)object


線(xiàn)條的定位公式:

 


from="x1,y1" to="x2,y2" 是 VML 里定位線(xiàn)條的方式

當(dāng)前節(jié)點(diǎn)是父節(jié)點(diǎn)的左邊子節(jié)點(diǎn),則公式為:
from = 父節(jié)點(diǎn)的left + 偏移量(15) , 父節(jié)點(diǎn)的top + 偏移量(32)
to = 父節(jié)點(diǎn)的left + 偏移量(30) , 父節(jié)點(diǎn)的top - 偏移量(2)

當(dāng)前節(jié)點(diǎn)是父節(jié)點(diǎn)的右邊子節(jié)點(diǎn),則公式為:
from = 父節(jié)點(diǎn)的left + 偏移量(35) ,父節(jié)點(diǎn)的top + 偏移量(32)
to = 父節(jié)點(diǎn)的left + 偏移量(20) ,父節(jié)點(diǎn)的top - 偏移量(2)

 


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

如果只是單純的做一個(gè)公司結(jié)構(gòu)圖的話(huà),會(huì)更簡(jiǎn)單很多。
下面是賽揚(yáng)的思路,我也是在他的基礎(chǔ)上深入一點(diǎn)而已。

 

首先計(jì)算最下層節(jié)點(diǎn)個(gè)數(shù),得出寬度,
然后應(yīng)該根據(jù)節(jié)點(diǎn)的從屬關(guān)系計(jì)算其上層節(jié)點(diǎn)位置,遞歸。
每一層級(jí)的節(jié)點(diǎn)要按從屬關(guān)系先排序
首先設(shè)“基本值”=節(jié)點(diǎn)應(yīng)向右偏移量
每個(gè)包含子節(jié)點(diǎn)的節(jié)點(diǎn)的left值等于它所擁有的節(jié)點(diǎn)所占寬度的一半加上基本值

 

后話(huà):

最近不知為何,網(wǎng)絡(luò)一直都不好。斷線(xiàn)的時(shí)間比在線(xiàn)的時(shí)間多。
所以沒(méi)對(duì)代碼簡(jiǎn)化,其實(shí),要完善的功能還有很多,比如:
需要加右鍵菜單
右鍵菜單內(nèi)含新建節(jié)點(diǎn)、修改節(jié)點(diǎn)名稱(chēng)、改變關(guān)聯(lián)關(guān)系等
在每一個(gè)節(jié)點(diǎn)上都可右鍵打開(kāi)這個(gè)節(jié)點(diǎn)的右鍵菜單
 

 

 

講解:
1)flow2.xml 是數(shù)據(jù)文件,相信大家都不會(huì)有問(wèn)題。
2)flow2.xsl 是格式文件,有幾個(gè)地方要注意。 
(1)腳本中:

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

(1)和(2)的作用都是返回由 select 參數(shù)給出的表達(dá)式的字符串值。
他們的搜索條件相同,所以返回的值也一樣。
只不過(guò)是使用的場(chǎng)合不同,他們的書(shū)寫(xiě)形式也就不一樣。
xsl:apply-templates select="team" order-by="blue_ID"/>
比如我們想生成以下代碼
div 名稱(chēng)=“參數(shù)值”>內(nèi)容/div>


我們假設(shè)名稱(chēng)為“name”,參數(shù)值為XML數(shù)據(jù)中當(dāng)前節(jié)點(diǎn)下面的子節(jié)點(diǎn)book的值


第一種寫(xiě)法是先加屬性名稱(chēng),再加參數(shù)值
div>
xsl:attribute name="name">
xsl:value-of select="./book/text()"/> /xsl:attribute>
內(nèi)容
/div>

第二種寫(xiě)法是直接加屬性名稱(chēng)和參數(shù)值
div name="{./book/text()}">內(nèi)容/div>

具體的使用你可以看我寫(xiě)的代碼中的例子。

XSL在正式的 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 的標(biāo)準(zhǔn)里

xsl:value-of select="./book/text()"/>
作用是:只是把他的文本值寫(xiě)出來(lái),而
xsl:value-of select="./book"/>
是把他的文本值和他的所有子節(jié)點(diǎn)的內(nèi)容顯示出來(lái)。
大家可以試驗(yàn)一下,輸出一個(gè)有子節(jié)點(diǎn)的,一個(gè)無(wú)子節(jié)點(diǎn)的
看看顯示的結(jié)果是否相同。


(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" ?>
另外說(shuō)一點(diǎn):
在大多的XML教科書(shū)中所顯示的代碼中很少會(huì)加上encoding="gb2312" ,
因此我們?cè)赬ML中用到中文的時(shí)候會(huì)報(bào)錯(cuò),原因就是沒(méi)有寫(xiě)這個(gè)申明。

 


后記:
這里說(shuō)的是一種思路。如果觸類(lèi)旁通,自然能夠派上用場(chǎng)。 

您可能感興趣的文章:
  • Python構(gòu)建XML樹(shù)結(jié)構(gòu)的方法示例
  • 關(guān)于html嵌入xml數(shù)據(jù)島如何穿過(guò)樹(shù)形結(jié)構(gòu)關(guān)系的問(wèn)題
  • 一個(gè)很簡(jiǎn)單的jquery+xml+ajax的無(wú)刷新樹(shù)結(jié)構(gòu)(無(wú)css,后臺(tái)是c#)
  • Dom遍歷XML的一個(gè)例子,結(jié)果為樹(shù)狀結(jié)構(gòu)
  • 簡(jiǎn)單了解XML 樹(shù)結(jié)構(gòu)

標(biāo)簽:寧夏 拉薩 西雙版納 黃石 宿遷 果洛 益陽(yáng) 德州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《XML卷之實(shí)戰(zhàn)錦囊(5):結(jié)構(gòu)樹(shù)圖》,本文關(guān)鍵詞  XML,卷之,實(shí)戰(zhàn),錦囊,結(jié)構(gòu),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《XML卷之實(shí)戰(zhàn)錦囊(5):結(jié)構(gòu)樹(shù)圖》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于XML卷之實(shí)戰(zhàn)錦囊(5):結(jié)構(gòu)樹(shù)圖的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    喜德县| 黄骅市| 化德县| 凤庆县| 庆云县| 唐山市| 昭苏县| 克拉玛依市| 武宣县| 高碑店市| 平乡县| 民勤县| 基隆市| 宁远县| 星座| 柘荣县| 穆棱市| 岳普湖县| 奉节县| 南投县| 环江| 墨竹工卡县| 扬州市| 山西省| 赤城县| 北票市| 武穴市| 布拖县| 旺苍县| 宁远县| 广水市| 普定县| 闻喜县| 西和县| 南涧| 泸水县| 柳河县| 横峰县| 元江| 温州市| 上栗县|