motivation:
J'ai d'abord pensé à créer un arbre binaire parce que j'avais besoin de créer un organigramme de l'entreprise. L’approche précédente consistait à dessiner une image directement à l’aide d’un logiciel graphique. Cela a l'air génial, mais vous devez en peindre un nouveau à chaque fois qu'il y a des changements. En revanche, l'affichage et la disposition des lignes sur les pages web sont assez limités. La composition et le positionnement basés sur des données générées dynamiquement sont très difficiles et l'esthétique n'est pas satisfaisante. Après avoir fait plusieurs tentatives, j'ai décidé d'utiliser XML+XSL pour les opérations sur les données ; d'utiliser VML pour embellir les lignes et d'utiliser JAVASCRIPT pour positionner les objets.
Matériel:
L'arborescence de la structure du volume XML comporte 2 fichiers : flow2.xml et flow2.xsl
Effet:
Parcourez ici
expliquer:
Idée d'arbre binaire (1)
<html xmlns:v="urn:schemas-microsoft-com:vml">
<STYLE>
v:* { COMPORTEMENT : url(#default#VML) }
</STYLE>
<v:group id="group1" name="group1" coordsize = "100,100">
…
</v:groupe>
Ce sont les formats de base de VML, je ne les expliquerai donc pas en détail.
XML est une structure arborescente Lorsque nous lisons chaque donnée, nous devons le faire.
L'arborescence de données XML est parcourue. Les opérations récursives sont l'un des avantages de XSL.
J'ai également décidé d'utiliser XSL après avoir utilisé diverses autres méthodes pour effectuer des opérations de traversée et j'ai échoué.
<FlowRoot>
<vcTitle>Arbre binaire - diagramme de structure</vcTitle>
<Auteur>Vol à voile</Auteur>
<Email>[email protected]</Email>
<NœudFlux>
<iProcess>1</iProcess>
<vcCourse>Premier nœud</vcCourse>
<iSuivantOui>
<NœudFlux>
<iProcess>2</iProcess>
<vcCourse>Deuxième nœud</vcCourse>
<iSuivantOui>…</iSuivantOui>
<iNextNo>…</iNextNo>
</FlowNode>
</iSuivantOui>
<iNumSuivant>
<NœudFlux>
<iProcess>3</iProcess>
<vcCourse>Le troisième nœud</vcCourse>
<iSuivantOui>…</iSuivantOui>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextNo>
</FlowNode>
</FlowRoot>
La logique est très simple. Il y a deux nœuds enfants (2, 3) sous le nœud actuel (1).
Positionnez simplement le nœud 2 et le nœud 3 en bas à gauche et en bas à droite du nœud 1.
Ici, j'utilise respectivement le vert et le rouge pour les lignes de connexion des nœuds gauche et droit pour un affichage facile.
Nous avons parlé plus tôt de la fonction récursive de XSL Afin de voir plus clairement chaque étape d'affichage détaillée, il vous suffit d'imiter le code suivant et d'ajouter une instruction d'alerte.
<xsl:template match="FlowNode">
…
<Langage SCRIPT="JavaScript1.2">
…
alert('afficher étape par étape');
…
</SCRIPT>
…
</xsl:modèle>
Après avoir regardé le ralenti ci-dessus, pouvez-vous comprendre mes pensées ?
Idée d'arbre binaire (2)
Mon idée est très simple :
(1) Lisez les données du nœud actuel et générez un nouvel objet en utilisant VML.
Attribuez une valeur initiale à l'objet (telle que le nom, l'identifiant, le style, etc.)
(2) Utilisez le contrôle de script pour positionner l'objet actuel (3) Ajoutez des flèches et des lignes entre le nœud actuel et son nœud parent.
(4) Continuez à trouver les nœuds enfants du nœud actuel et bouclez jusqu'à la fin.
Autrement dit, tous les nœuds ont été parcourus et l'arborescence a été générée.
<xsl:template match="FlowNode">
…
<xsl:apply-templates />
…
</xsl:modèle>
<xsl:template match="iNextYes">
<xsl:apply-templates select="./FlowNode" />
</xsl:template>
<xsl:template match="iNextNo">
<xsl:apply-templates select="./FlowNode" />
</xsl:modèle>
L'ensemble du processus récursif est complété par les trois modules (modèles) ci-dessus.
Le premier modèle appelle les deux modèles suivants lors de la correspondance avec le modèle de chaque nœud enfant dans le nœud actuel ; et les deux derniers modèles appellent le premier modèle lors d'une exécution spécifique, ce qui équivaut à une fonction récursive.
grammaire:
Pour faire correspondre les modèles de chaque nœud enfant dans le nœud actuel, utilisez le formulaire de base de l'élément <xsl:apply-templates />.
Sinon, le nœud correspondant est déterminé par la valeur de l'expression XPath dans le paramètre select, telle que <xsl:apply-templates select="./FlowNode" />
Les fonctions de (1) et (2) doivent renvoyer la valeur de chaîne de l'expression donnée par le paramètre select.
Leurs conditions de recherche sont les mêmes, donc les valeurs renvoyées sont également les mêmes.
C'est juste que leurs formes d'écriture sont différentes selon les occasions où elles sont utilisées.
(1) <xsl:value-of select="./iProcess/text()" />
(2) {./iProcess/text()}
Certaines variables sont définies ici, et le positionnement du nœud se base sur ces variables pour appeler la formule de calcul.
root_left //La marge gauche de la racine = la largeur allouée de toutes les feuilles (y*10) + la largeur de toutes les feuilles (y*50) + la valeur de base de la marge gauche (10)
root_top //La marge supérieure de la racine = la valeur de base de la marge supérieure (10)
objOval //L'objet courant est un objet
objOval_iProcess //Valeur d'étape de l'objet courant
objParentOval //Le nœud parent de l'objet courant est un objet
objParentOval_iProcess //La valeur de pas du nœud parent de l'objet actuel
objParent_name //Le nom du nœud parent de l'objet actuel
Leaf_left //Le nombre de feuilles gauches parmi tous les nœuds enfants de l'objet actuel
Leaf_right //Le nombre de feuilles droites parmi tous les nœuds enfants de l'objet actuel
Leaf_sum //Le nombre de feuilles parmi tous les nœuds enfants de l'objet actuel.
Feuille : fait référence au nœud actuel n'ayant aucun nœud enfant.
Formule de positionnement du nœud :
(1) Le nœud actuel est le nœud racine
//La position de la racine
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//La fonction de la fonction parseInt() est de prendre la valeur entière, sinon ce sera NAN
//La fonction de la fonction isNaN() est de déterminer si la valeur obtenue par parseInt est un entier.
(2) Le nœud actuel est le nœud enfant gauche du nœud parent
1) Les conditions de jugement sont : Le nom du nœud parent de l'objet actuel = 'iNextYes'
…
2) S'il y a une feuille enfant droite, la formule est :
La gauche du nœud courant = la gauche du nœud parent - la largeur totale de la feuille enfant droite du nœud courant - la largeur du nœud courant
3) S'il n'y a pas de feuille enfant droite, mais qu'il y a une feuille enfant gauche , la formule est :
La gauche du nœud actuel = la gauche du nœud parent - la largeur totale de la feuille enfant gauche du nœud actuel
4) Si le nœud actuel lui-même est une feuille, la formule est :
La gauche du nœud actuel = la gauche du nœud parent - la largeur du nœud actuel...
(3) Le nœud actuel est le nœud enfant droit du nœud parent
1) Les conditions de jugement sont : Le nom du nœud parent de l'objet actuel = 'iNextNo'
…
2) S'il y a une feuille enfant gauche, la formule est :
La gauche du nœud courant = la gauche du nœud parent + la largeur totale de la feuille enfant gauche du nœud courant + la largeur du nœud courant
3) S'il n'y a pas de feuille enfant gauche, mais qu'il y a une feuille enfant droite , la formule est :
La gauche du nœud courant = la gauche du nœud parent + la largeur totale de la feuille enfant droite du nœud courant
4) Si le nœud courant lui-même est une feuille, la formule est :
La gauche du nœud actuel = la gauche du nœud parent + la largeur du nœud actuel...
Les formules (2) et (3) obtiennent toutes deux la gauche du nœud actuel, et nous devons également obtenir le haut du nœud actuel.
Formule très simple : haut du nœud actuel = haut du nœud parent + décalage (80)
Idée d'arbre binaire (3)
Idées de positionnement pour relier les lignes :
(1) Trouver les positions du nœud actuel et du nœud parent (2) Déterminer si le nœud actuel est le nœud enfant gauche ou le nœud enfant droit du nœud parent (3) Tracer une ligne
Certaines variables sont définies ici.
objOval //Le nœud actuel est un objet
objParentOval //Le nœud parent de l'objet courant est un objet
objLine //La ligne courante est un objet
Formule de positionnement de ligne :
from="x1,y1" to="x2,y2" est la manière de positionner les lignes dans VML.
Le nœud actuel est le nœud enfant gauche du nœud parent, alors la formule est :
from = gauche du nœud parent + décalage (15), haut du nœud parent + décalage (32)
to = gauche + décalage (30) du nœud parent, haut - décalage (2) du nœud parent.
Le nœud actuel est le nœud enfant droit du nœud parent, alors la formule est :
de = gauche du nœud parent + décalage (35), haut du nœud parent + décalage (32)
à = à gauche du nœud parent + décalage (20), haut du nœud parent - décalage (2)
C'est tout ce à quoi je peux penser.
Ce serait beaucoup plus simple si nous faisions simplement un organigramme de l’entreprise.
Ce qui suit est l'idée de Cy Young, et j'approfondis juste un peu cette base.
Calculez d'abord le nombre de nœuds au niveau inférieur pour obtenir la largeur,
La position supérieure du nœud doit ensuite être calculée en fonction de son affiliation, de manière récursive.
Les nœuds de chaque niveau doivent être triés en fonction de leur affiliation. Tout d'abord, définissez la "valeur de base" = le nœud doit être décalé vers la droite. La valeur gauche de chaque nœud contenant des nœuds enfants est égale à la moitié de la largeur du nœud. possède plus la valeur de base.
Post-scriptum :
Pour une raison quelconque, Internet a été mauvais ces derniers temps. Passez plus de temps hors ligne qu'en ligne.
Le code n’a donc pas été simplifié. En fait, de nombreuses fonctions doivent encore être améliorées, telles que :
Vous devez ajouter un menu contextuel. Le menu contextuel contient la possibilité de créer de nouveaux nœuds, de modifier les noms de nœuds, de modifier les associations, etc. Vous pouvez cliquer avec le bouton droit sur chaque nœud pour ouvrir le menu contextuel de ce nœud. .
expliquer:
1) flow2.xml est un fichier de données, je pense que tout le monde n'aura aucun problème.
2) flow2.xsl est un fichier de format, il y a plusieurs choses auxquelles il faut faire attention.
(1) Dans le script :
(1) <xsl:value-of select="./iProcess/text()" />;
(2) {./iProcess/text()}
Les fonctions de (1) et (2) doivent renvoyer la valeur de chaîne de l'expression donnée par le paramètre select.
Leurs conditions de recherche sont les mêmes, donc les valeurs renvoyées sont également les mêmes.
C'est juste que leurs formes d'écriture sont différentes selon les occasions où elles sont utilisées.
<xsl:apply-templates select="team" order-by="blue_ID"/>
Par exemple, nous voulons générer le code suivant
<div name="parameter value">Contenu</div>
Nous supposons que le nom est "name" et que la valeur du paramètre est la valeur du nœud enfant book sous le nœud actuel dans les données XML.
La première façon de l'écrire consiste à ajouter d'abord le nom de l'attribut, puis la valeur du paramètre.
<div>
<xsl:attribute name="nom">
<xsl:value-of select="./book/text()"/> </xsl:attribute>
contenu
</div>
La deuxième façon d'écrire est d'ajouter directement le nom de l'attribut et la valeur du paramètre
<div name="{./book/text()}">Contenu</div>
Pour une utilisation spécifique, vous pouvez voir les exemples dans le code que j'ai écrit.
XSL est dans le standard officiel xmlns:xsl=" http://www.w3.org/1999/XSL/Transform "
<xsl:value-of select="./book/text()"/>
La fonction est la suivante : écrivez simplement sa valeur de texte, et
<xsl:value-of select="./book"/>
Il affiche sa valeur texte et le contenu de tous ses nœuds enfants.
Vous pouvez l'essayer et en afficher un avec des nœuds enfants et un sans nœuds enfants pour voir si les résultats affichés sont les mêmes.
(2) Remarque :
IE5 ne prend pas en charge <tag att="{xpath}">
Voulez-vous utiliser
<tag><xsl:attribute name="att"><xsl:value-of select="xpath"></xsl:attribute>
doit être utilisé
xmlns:xsl=" http://www.w3.org/TR/WD-xsl "
<?xml version="1.0" encoding="gb2312" ?>
Encore une chose :
Encoding="gb2312" est rarement ajouté au code affiché dans la plupart des manuels XML.
Par conséquent, lorsque nous utilisons le chinois en XML, une erreur sera signalée. La raison est que cette déclaration n'est pas écrite.
post-scriptum :
Ce dont je parle ici, c'est d'une façon de penser. Si vous faites une analogie, elle vous sera naturellement utile.