Как я могу создать дерево из плоского списка XML с помощью XSLT?

Вот пример того, как этот код должен быть написан (даже если все еще есть ужасы)

// declare them here and not in a function where they will be redone each time the function is called

const
  file_IHM  = document.querySelector('#doclicense')
  ,
  type_IHM  = document.querySelector('#accountType')  // and not with .value ...!
;


type_IHM.onchange = function()
{
  file_IHM.style.display = (this.value==='doctor')?"block":"none"; 

  console.log('type_IHM.value',  this.value );

}
#doclicense { display : none; } 
<div>
  <select id="accountType" name="type" class="form-control" >  <!--  let the js in the js part -->
    <option required>Account Type</option>
    <option value="doctor"  id="doctor"  >Doctor</option>
    <option value="regular" id="regular" >Regular Account</option>
  </select>
</div>

<div class="file-class" id="doclicense">  <!--  do not use class="hidden... -->
  <input type="file" name="license" />
  <input type="submit" />   <!-- there is no form anywhere...   why don't you use <button> ?? -->
</div>
[ 116]
6
задан Paŭlo Ebermann 30 October 2011 в 23:04
поделиться

3 ответа

В XSLT 2.0 это было бы довольно легко с новыми функциями группировки.

В XSLT 1.0 это немного более сложно, но это работает:

<xsl:template match="/tree">
    <xhtml>
        <head/>
        <body>
            <ul>
                <xsl:apply-templates select="node[depth='0']"/>
                </ul>
            </body>
        </xhtml>
    </xsl:template>

<xsl:template match="node">
    <xsl:variable name="thisNodeId" select="generate-id(.)"/>
    <xsl:variable name="depth" select="depth"/>
    <xsl:variable name="descendants">
        <xsl:apply-templates select="following-sibling::node[depth = $depth + 1][preceding-sibling::node[depth = $depth][1]/generate-id() = $thisNodeId]"/>
        </xsl:variable>
    <li>
        <xsl:value-of select="name"/>
        </li>
    <xsl:if test="$descendants/*">
        <ul>
            <xsl:copy-of select="$descendants"/>
            </ul>
        </xsl:if>
    </xsl:template>

Суть дела является длинной и ужасной переменной "потомков", которая ищет узлы после текущего узла, которые имеют ребенка "глубины", больше, чем текущая глубина, но не являются после другого узла, который имел бы ту же глубину как текущая глубина (потому что, если бы они были, они были бы детьми того узла вместо текущего).

BTW там является ошибкой в Вашем результате в качестве примера: "Flash" должен быть ребенком "MP3-ПЛЕЕРОВ" и не одноуровневого элемента.

Править

На самом деле (как упомянуто в комментариях), в "чистом" XSLT 1.0 это не работает по двум причинам: выражение пути использует генерировать-идентификатор () неправильно, и нельзя использовать "фрагмент дерева результата" в выражении пути.

Вот корректная версия XSLT 1.0 шаблона "узла" (успешно протестированный с саксом 6.5), который не использует EXSLT, ни XSLT 1.1:

<xsl:template match="node">
    <xsl:variable name="thisNodeId" select="generate-id(.)"/>
    <xsl:variable name="depth" select="depth"/>
    <xsl:variable name="descendants">
        <xsl:apply-templates select="following-sibling::node[depth = $depth + 1][generate-id(preceding-sibling::node[depth = $depth][1]) = $thisNodeId]"/>
        </xsl:variable>
    <xsl:variable name="descendantsNb">
        <xsl:value-of select="count(following-sibling::node[depth = $depth + 1][generate-id(preceding-sibling::node[depth = $depth][1]) = $thisNodeId])"/>
        </xsl:variable>
    <li>
        <xsl:value-of select="name"/>
        </li>
    <xsl:if test="$descendantsNb &gt; 0">
        <ul>
            <xsl:copy-of select="$descendants"/>
            </ul>
        </xsl:if>
    </xsl:template>

Конечно, нужно учесть выражение пути, которое повторяется, но без способности превратить "фрагменты дерева результата" в XML, который может на самом деле быть обработан, я не знаю, возможно ли это? (запись пользовательской функции добилась бы цели, конечно, но затем намного более просто использовать EXSLT),

Нижняя строка: используйте XSLT 1.1 или EXSLT, если Вы можете!

2-е Редактирование

Чтобы постараться не повторять выражение пути, можно также забыть тест в целом, который просто приведет к некоторым, освобождают это, можно или уехать в результате или выполнить последующую обработку для устранения.

1
ответ дан 17 December 2019 в 00:15
поделиться

Та форма плоского списка очень тверда работать с в xslt, поскольку необходимо найти положение следующей группировки и т.д. Можно ли использовать другой xml? Например, с плоским xml:

<?xml version="1.0" encoding="utf-8" ?>
<tree>
  <node key="0">root</node>
  <node key="1" parent="0">TELEVISIONS</node>
  <node key="2" parent="1">TUBE</node>
  <node key="3" parent="1">LCD</node>
  <node key="4" parent="1">PLASMA</node>
  <node key="5" parent="0">PORTABLE ELECTRONICS</node>
  <node key="6" parent="5">MP3 PLAYERS</node>
  <node key="7" parent="6">FLASH</node>
  <node key="8" parent="5">CD PLAYERS</node>
  <node key="9" parent="5">2 WAY RADIOS</node>
</tree>

Это становится тривиальным, чтобы сделать (очень эффективно):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="nodeChildren" match="/tree/node" use="@parent"/>
  <xsl:template match="tree">
    <ul>
      <xsl:apply-templates select="node[not(@parent)]"/>
    </ul>
  </xsl:template>
  <xsl:template match="node">
    <li>
      <xsl:value-of select="."/>
      <ul>
        <xsl:apply-templates select="key('nodeChildren',@key)"/>
      </ul>
    </li>
  </xsl:template>
</xsl:stylesheet>

Это - опция?

Конечно, при создании xml как иерархии, это еще легче;-p

5
ответ дан 17 December 2019 в 00:15
поделиться

Вы на самом деле не сказали, на что Вы хотели бы, чтобы вывод HTML был похож, но я могу сказать Вам, который с точки зрения XSLT, идущей от плоской структуры до дерева, будет сложным и дорогим, если Вы также основываете это на положении объектов в дереве и их отношении к одноуровневым элементам.

Было бы намного лучше предоставить a <parent> атрибут/узел, чем <depth>.

0
ответ дан 17 December 2019 в 00:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: