Heim >Backend-Entwicklung >XML/RSS-Tutorial >Praktische Tipps zum XML-Volume (5): Strukturbaumdiagramm
Motivation:
Ich habe ursprünglich daran gedacht, einen Binärbaum zu erstellen, weil ich ein Unternehmensstrukturdiagramm erstellen musste. Der bisherige Ansatz bestand darin, ein Bild direkt mit einer Grafiksoftware zu zeichnen. Es ist schön anzusehen, aber bei jeder Änderung muss man es neu anmalen. Andererseits sind die Darstellung und Anordnung von Zeilen auf Webseiten recht eingeschränkt. Satz und Positionierung auf Basis dynamisch generierter Daten sind sehr schwierig und die Ästhetik nicht zufriedenstellend. Nachdem ich verschiedene Versuche unternommen hatte, entschied ich mich, XML+XSL für Datenoperationen zu verwenden; VML zum Verschönern von Linien und JAVASCRIPT zum Positionieren von Objekten zu verwenden.
Materialien:
XML-Volumenstruktur-Baumdiagramm
Es gibt 2 Dateien: flow2.xml und flow2.xsl
Effekt:
Hier durchsuchen
Erklärung:
Binär Baumidee (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>
Dies sind die Grundformate von VML, daher werde ich sie nicht im Detail erklären.
XML ist eine Baumstruktur. Wenn wir alle Daten lesen, müssen wir diesen
XML-Datenbaum durchlaufen. Rekursive Operationen sind einer der Vorteile von XSL.
Ich habe mich auch
für die Verwendung von XSL entschieden, nachdem ich verschiedene andere Methoden zum Durchführen von Durchlaufoperationen verwendet hatte und fehlgeschlagen war.
<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>
Die Logik ist sehr einfach, es gibt zwei untergeordnete Knoten (2, 3) unter dem aktuellen Knoten (1).
Positionieren Sie Knoten 2 und Knoten 3 einfach unten links und unten rechts von Knoten 1.
Hier verwende ich zur einfacheren Anzeige Grün und Rot für die Verbindungslinien des linken bzw. rechten Knotens.
Wir haben zuvor über die rekursive Funktion von XSL gesprochen. Um jeden detaillierten
Anzeigeschritt klarer zu sehen, müssen Sie nur den folgenden Code nachahmen und eine Warnanweisung hinzufügen.
<xsl:template match="FlowNode">…<SCRIPT language="JavaScript1.2">…alert('逐步显示');…</SCRIPT>…</xsl:template>
Wenn Sie sich die Zeitlupe oben ansehen, können Sie meine Gedanken verstehen?
Binärbaum-Idee (2)
Meine Idee ist sehr einfach:
(1) Lesen Sie die Daten des aktuellen Knotens und Verwenden Sie VML. Erzeugen Sie ein neues Objekt.
Weisen Sie dem Objekt einen Anfangswert zu (z. B. Name, ID, Stil usw.)
(2) Verwenden Sie die Skriptsteuerung, um das aktuelle Objekt zu positionieren
(3) Fügen Sie einen Pfeil zwischen dem aktuellen Knoten und hinzu sein übergeordneter Knoten, Linie.
(4) Suchen Sie weiterhin nach den untergeordneten Knoten des aktuellen Knotens und wiederholen Sie die Schleife bis zum Ende.
Das heißt, alle Knoten wurden durchlaufen und der Baum wurde generiert.
<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>
Der gesamte rekursive Prozess wird durch die oben genannten drei Module (Vorlage) vervollständigt.
Die erste Vorlage
ruft die nächsten beiden Vorlagen auf, wenn sie mit der Vorlage jedes Unterknotens im aktuellen Knoten übereinstimmt, und die letzten beiden Vorlagen rufen die erste Vorlage auf, wenn
ausgeführt wird, was a entspricht rekursive Funktion.
Syntax:
Um die Vorlage jedes untergeordneten Knotens im aktuellen Knoten nacheinander anzupassen, sollte die Grundform des
-Elements verwendet werden24b44b04e52c4e2656608cf3ab6aab43.
Andernfalls wird der passende Knoten durch den Wert des XPath-Ausdrucks im Auswahlparameter
bestimmt, z. B. a4ff84829f0c6689de63321b743d97eb
Die Funktionen von (1) und (2) bestehen darin, den Zeichenfolgenwert des durch den Auswahlparameter angegebenen Ausdrucks zurückzugeben.
Ihre Suchbedingungen sind gleich, daher sind auch die zurückgegebenen Werte gleich.
Es ist nur so, dass die Anlässe, zu denen sie verwendet werden, unterschiedlich sind und auch ihre Schreibformen unterschiedlich sind.
(1) 4e771df31dc7c4d0227645e23ff3015c
(2) {./iProcess/text()}
Hier werden einige Variablen definiert, und die Positionierung des Knotens basiert auf diesen Variablen, um die Berechnungsformel aufzurufen.
root_left //Der linke Rand der Wurzel = die zugewiesene Breite aller Blätter (y*10) + die Breite aller Blätter (y*50) + der Grundwert des linken Randes (10)
root_top //Der obere Rand der Wurzel = Grundwert des oberen Randes (10)
objOval //Das aktuelle Objekt ist ein Objekt
objOval_iProcess //Der Schrittwert des aktuellen Objekts
objParentOval //Das übergeordnete Objekt Knoten des aktuellen Objekts ist ein Objekt
objParentOval_iProcess //Der Schrittwert des übergeordneten Knotens des aktuellen Objekts
objParent_name //Der Name des übergeordneten Knotens des aktuellen Objekts
Leaf_left //Die Anzahl der linken Blätter unter allen untergeordnete Knoten des aktuellen Objekts
Leaf_right //Alle rechten Blätter des aktuellen Objekts in untergeordneten Knoten
Leaf_sum //Anzahl der Blätter in allen untergeordneten Knoten des aktuellen Objekts
Blatt: bedeutet dass der aktuelle Knoten keine untergeordneten Knoten hat
Knotenpositionierungsformel:
(1) Der aktuelle Knoten ist der Wurzelknoten
//根的位置 SobjOval.style.left=parseInt(root_left); SobjOval.style.top=parseInt(root_top); //parseInt() 函数的作用是取整数值,如果不是则为NAN //isNaN()函数的作用是判断parseInt取得的是否为整数
(2) Der aktuelle Knoten ist der linke untergeordnete Knoten des übergeordneten Knotens
1) Die Bedingung für die Beurteilung ist: Der Name des übergeordneten Knotens des aktuellen Objekts =' iNextYes'
…
2) Wenn es ein rechtes untergeordnetes Blatt gibt, lautet die Formel:
links vom aktuellen Knoten = links vom übergeordneten Knoten – Gesamtbreite des rechten untergeordneten Blatts des aktuellen Knotens – Breite des aktuellen Knotens
3) Wenn es kein rechtes untergeordnetes Blatt, aber ein linkes untergeordnetes Blatt gibt, lautet die Formel:
Aktueller Knoten Die Linke = die Linke des übergeordneten Knotens – die Summe Breite des linken untergeordneten Blatts des aktuellen Knotens
4) Wenn der aktuelle Knoten selbst ein Blatt ist, lautet die Formel:
die linke Seite des aktuellen Knotens = die linke Seite des übergeordneten Knotens – die aktuelle Die Breite des Knotens
…
(3) Der aktuelle Knoten ist der rechte untergeordnete Knoten des übergeordneten Knotens
1) Die Bedingungen für die Beurteilung sind: Der Name des übergeordneten Knotens des aktuellen Objekts='iNextNo'
…
2) Wenn es ein linkes untergeordnetes Blatt gibt, lautet die Formel:
Die linke Seite des aktuellen Knotens=the links vom übergeordneten Knoten + die Gesamtzahl der linken untergeordneten Blätter des aktuellen Knotens. Breite + Breite des aktuellen Knotens
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"/>
比如我们想生成以下代码
bba950c6d155ac5073309a6041296da9内容94b3e26ee717c64999d7867364b1b4a3
我们假设名称为“name”,参数值为XML数据中当前节点下面的子节点book的值
第一种写法是先加属性名称,再加参数值
<p> <xsl:attribute name="name"> <xsl:value-of select="./book/text()"/> </xsl:attribute> 内容 </p>
第二种写法是直接加属性名称和参数值
<p name="{./book/text()}">内容</p>
具体的使用你可以看我写的代码中的例子。
XSL在正式的 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 的标准里
<xsl:value-of select="./book/text()"/>
作用是:只是把他的文本值写出来,而
<xsl:value-of select="./book"/>
是把他的文本值和他的所有子节点的内容显示出来。
大家可以试验一下,输出一个有子节点的,一个无子节点的
看看显示的结果是否相同。
(2)需要注意:
IE5 不支持 c55c83ef8ee979923031582b93a38c44
要用
<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中用到中文的时候会报错,原因就是没有写这个申明。
后记:
这里说的是一种思路。如果触类旁通,自然能够派上用场。
以上就是XML卷之实战锦囊(5):结构树图的内容,更多相关内容请关注PHP中文网(www.php.cn)!