мотивация:
Впервые я подумал о создании двоичного дерева, потому что мне нужно было построить структуру компании. Предыдущий подход заключался в том, чтобы нарисовать изображение напрямую с помощью графического программного обеспечения. Выглядит великолепно, но каждый раз, когда происходят изменения, нужно красить новый. С другой стороны, отображение и расположение строк на веб-страницах весьма ограничено. Набор текста и позиционирование на основе динамически генерируемых данных очень сложны, а эстетика неудовлетворительна. После различных попыток я решил использовать XML+XSL для операций с данными, использовать VML для украшения строк и использовать JAVASCRIPT для позиционирования объектов.
Материал:
Древовидная диаграмма тома XML состоит из двух файлов: flow2.xml и flow2.xsl.
Эффект:
Просмотреть здесь
объяснять:
Идея двоичного дерева (1)
<html xmlns:v="urn:schemas-microsoft-com:vml">
<СТИЛЬ>
v:* { ПОВЕДЕНИЕ: url(#default#VML) }
</СТИЛЬ>
<v:group id="group1" name="group1" coordsize = "100,100">
…
</v:группа>
Это базовые форматы VML, поэтому я не буду их подробно объяснять.
XML — это древовидная структура. Когда мы читаем каждые данные, нам нужно
Просматривается дерево данных XML. Рекурсивные операции — одно из преимуществ XSL.
Я также решил использовать XSL после того, как использовал различные другие методы для выполнения операций обхода, но потерпел неудачу.
<FlowRoot>
<vcTitle>Диаграмма структуры двоичного дерева</vcTitle>
<Автор>Парусный спорт</Автор>
<Электронная почта>[email protected]</Email>
<FlowNode>
<iProcess>1</iProcess>
<vcCourse>Первый узел</vcCourse>
<iСледующийДа>
<FlowNode>
<iProcess>2</iProcess>
<vcCourse>Второй узел</vcCourse>
<iNextДа>…</iNextДа>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextДа>
<iNextNo>
<FlowNode>
<iProcess>3</iProcess>
<vcCourse>Третий узел</vcCourse>
<iNextДа>…</iNextДа>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextNo>
</FlowNode>
</FlowRoot>
Логика очень проста. Под текущим узлом (1) есть два дочерних узла (2, 3).
Просто расположите узел 2 и узел 3 в левом нижнем и правом нижнем углу узла 1.
Здесь я использую зеленый и красный цвета для соединительных линий левого и правого узлов соответственно для удобства отображения.
Ранее мы говорили о рекурсивной функции XSL. Чтобы более четко увидеть каждый подробный шаг отображения, вам нужно всего лишь имитировать следующий код и добавить оператор предупреждения.
<xsl:template match="FlowNode">
…
<SCRIPT Language="JavaScript1.2">
…
alert('показывать шаг за шагом');
…
</СКРИПТ>
…
</xsl:шаблон>
После просмотра замедленной съемки выше, можете ли вы понять мои мысли?
Идея двоичного дерева (2)
Моя идея очень проста:
(1) Прочтите данные текущего узла и сгенерируйте новый объект с помощью VML.
Присвойте объекту начальное значение (например, имя, идентификатор, стиль и т. д.).
(2) Используйте элемент управления скриптом, чтобы расположить текущий объект. (3) Добавьте стрелки и линии между текущим узлом и его родительским узлом.
(4) Продолжайте искать дочерние узлы текущего узла и повторяйте цикл до конца.
То есть все узлы пройдены и дерево создано.
<xsl:template match="FlowNode">
…
<xsl:apply-templates />
…
</xsl:шаблон>
<xsl:template match="iNextДа">
<xsl:apply-templates select="./FlowNode" />
</xsl:template>
<xsl:template match="iNextNo">
<xsl:apply-templates select="./FlowNode" />
</xsl:шаблон>
Весь рекурсивный процесс завершается тремя вышеуказанными модулями (шаблонами).
Первый шаблон вызывает следующие два шаблона при сопоставлении с шаблоном каждого дочернего узла в текущем узле, а последние два шаблона вызывают первый шаблон во время конкретного выполнения, что эквивалентно рекурсивной функции.
грамматика:
Чтобы поочередно сопоставить шаблоны каждого дочернего узла в текущем узле, используйте базовую форму элемента <xsl:apply-templates />.
В противном случае соответствующий узел определяется значением выражения 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 //Текущий объект является объектом
objOval_iProcess //Значение шага текущего объекта
objParentOval //Родительский узел текущего объекта является объектом
objParentOval_iProcess //Значение шага родительского узла текущего объекта
objParent_name //Имя родительского узла текущего объекта
Leaf_left //Количество левых листьев среди всех дочерних узлов текущего объекта
Leaf_right //Количество правых листьев среди всех дочерних узлов текущего объекта
Leaf_sum //Количество листьев среди всех дочерних узлов текущего объекта.
Leaf: относится к текущему узлу, не имеющему дочерних узлов.
Формула позиционирования узла:
(1) Текущий узел является корневым узлом.
//Положение корня
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
//Функция функции parseInt() — принять целочисленное значение, если нет, то это будет NAN
//Функция isNaN() — определить, является ли значение, полученное с помощью parseInt, целым числом.
(2) Текущий узел является левым дочерним узлом родительского узла.
1) Условия принятия решения: Имя родительского узла текущего объекта = «iNextДа»
…
2) Если есть правый дочерний лист, формула:
Левая часть текущего узла = левая часть родительского узла - общая ширина правого дочернего листа текущего узла - ширина текущего узла
3) Если правого дочернего листа нет, но есть левый дочерний лист , формула:
Левая часть текущего узла = левая часть родительского узла – общая ширина левого дочернего листа текущего узла.
4) Если текущий узел сам является листом, формула будет такой:
Слева от текущего узла = слева от родительского узла — ширина текущего узла...
(3) Текущий узел является правым дочерним узлом родительского узла.
1) Условия принятия решения: Имя родительского узла текущего объекта=’iNextNo’
…
2) Если есть левый дочерний лист, формула:
Левая часть текущего узла = левая часть родительского узла + общая ширина левого дочернего листа текущего узла + ширина текущего узла
3) Если левого дочернего листа нет, но есть правый дочерний лист , формула:
Левая часть текущего узла = левая часть родительского узла + общая ширина правого дочернего листа текущего узла.
4) Если текущий узел сам является листом, формула будет следующей:
Слева от текущего узла = слева от родительского узла + ширина текущего узла...
Формулы (2) и (3) получают левую часть текущего узла, и нам также нужно получить верхнюю часть текущего узла.
Очень простая формула: вершина текущего узла = вершина родительского узла + смещение (80).
Идея двоичного дерева (3)
Идеи расположения соединительных линий:
(1) Найдите положения текущего узла и родительского узла (2) Определите, является ли текущий узел левым дочерним узлом или правым дочерним узлом родительского узла (3) Нарисуйте линию
Здесь определены некоторые переменные.
objOval //Текущий узел является объектом
objParentOval //Родительский узел текущего объекта является объектом
objLine //Текущая строка является объектом
Формула позиционирования линии:
from="x1,y1" to="x2,y2" — это способ позиционирования строк в VML.
Текущий узел является левым дочерним узлом родительского узла, тогда формула:
from = левый угол родительского узла + смещение (15), верх родительского узла + смещение (32)
to = слева + смещение (30) родительского узла, сверху — смещение (2) родительского узла.
Текущий узел является правым дочерним узлом родительского узла, тогда формула:
from = слева от родительского узла + смещение (35), сверху родительского узла + смещение (32)
to = слева от родительского узла + смещение (20), сверху родительского узла - смещение (2)
Это все, о чем я могу думать.
Было бы гораздо проще, если бы мы просто составили схему структуры компании.
Нижеизложенное представляет собой идею Сая Янга, и я просто углубляюсь в его основу.
Сначала вычислите количество узлов на нижнем уровне, чтобы получить ширину.
Затем положение верхнего узла узла должно быть рассчитано рекурсивно на основе его принадлежности.
Узлы на каждом уровне должны быть отсортированы по их принадлежности. Сначала установите «базовое значение» = узел должен быть смещен вправо. Левое значение каждого узла, содержащего дочерние узлы, равно половине ширины узла. владеет плюс базовая стоимость.
Постскриптум:
Почему-то в последнее время интернет стал плохим. Проводите больше времени оффлайн, чем онлайн.
Таким образом, код не был упрощен. На самом деле, есть еще много функций, которые необходимо улучшить, например:
Вам необходимо добавить контекстное меню. Контекстное меню содержит возможность создавать новые узлы, изменять имена узлов, изменять ассоциации и т. д. Вы можете щелкнуть правой кнопкой мыши по каждому узлу, чтобы открыть контекстное меню этого узла. .
объяснять:
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 name="значение параметра">Содержимое</div>
Мы предполагаем, что имя — «имя», а значение параметра — это значение книги дочерних узлов текущего узла в данных XML.
Первый способ его записи — сначала добавить имя атрибута, а затем значение параметра.
<дел>
<xsl:attribute 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"coding="gb2312" ?>
Еще одна вещь:
Encoding="gb2312" редко добавляется к коду, показанному в большинстве учебников по XML.
Поэтому, когда мы используем китайский язык в XML, будет сообщено об ошибке. Причина в том, что это объявление не написано.
постскриптум:
Я говорю о образе мышления. Если провести аналогию, то она, естественно, пригодится.