Преодоление незакрытых тегов в xsl - PullRequest
1 голос
/ 28 апреля 2011

Я работаю над выпадающим меню, которое извлекает данные из списка Sharepoint и использует стиль xsl. Структура HTML представляет собой простой неупорядоченный список

<ul><li>parent page</li><ul><li>sub page 1</li><li>sub page2</li></ul></ul>

xsl проверяет, является ли элемент в списке родительской страницей или вложенной страницей, а также номер подстраницы. У родительских страниц есть номер, поэтому нужные подстраницы могут быть прикреплены к правильной родительской странице.

Базовый xsl для каждого предмета таков:

<xsl:for-each select="//Data/Row">
    <xsl:if test="./@Page_x0020_type = 0">
        <li >
            <a>
                <xsl:attribute name="href">
                    <xsl:value-of
                     select="./@Page_x002f_link_x0020_url"/>
                </xsl:attribute>
                <xsl:value-of select="./@Title0"/>
            </a>
        </li>
    </xsl:if>

Я хочу приравнять xsl к этому: Если это подстраница, добавьте к элементу тег ul, а если это последняя подстраница под родителем, добавьте закрывающий тег ul.

Как мне обойти тот факт, что xsl не позволит мне добавить незакрытый тег ul, потому что он (правильно) не знает, будет ли закрываться тег?

XML

    <Field Type="Text" 
           DisplayName="Page/link url" 
           Required="FALSE" 
           MaxLength="255" 
           Name="Page_x002f_link_x0020_url"/>
    <Field ReadOnly="TRUE" 
           Type="Computed" 
           Name="LinkTitle" 
           DisplayName="Page number"/>
    <Field Type="Text" 
           DisplayName="Title" 
           Required="FALSE" 
           MaxLength="255" 
           Name="Title0"/>  
    <Field Type="Choice" 
           DisplayName="Page type" 
           Required="FALSE" 
           Format="RadioButtons" 
           FillInChoice="FALSE" 
           Name="Page_x0020_type">    
           <CHOICES>  
               <CHOICE>0</CHOICE>  
               <CHOICE>1</CHOICE>  
           </CHOICES>  
           <DefaultFormula>=0</DefaultFormula>  
           <DefaultFormulaValue/>  
    </Field>
    <Field Type="Text" 
           DisplayName="Sub page number" 
           Required="FALSE" 
           MaxLength="2" 
           Name="Sub_x0020_page_x0020_number"/>
    <Field Type="Text" 
           DisplayName="Parent page number" 
           Required="FALSE" 
           MaxLength="1" 
           Name="Parent_x0020_page_x0020_number">
           <Default>0</Default>
    </Field>
</Schema>
<Data ItemCount="1">
    <Row Page_x002f_link_x0020_url="" 
         LinkTitle="" 
         Title0="" 
         Page_x0020_type="" 
         Sub_x0020_page_x0020_number="" 
         Parent_x0020_page_x0020_number="" 
         ul="" 
         _x003c_li_x003e__x003c_a_x003e_="" 
         _x003c__x002f_a_x003e__x003c__x0="" 
         _x003c_ul_x003e__x003c_li_x003e_="" 
         _x003c__x002f_a_x003e__x003c__x00="" 
         _x003c__x002f_a_x003e__x003c__x01=""/>

UPDATE:

Типы страниц:
  • Родитель <li>parent1</li>
  • Подстраница 1 - должна начинаться с <ul>...<li>sub page 1</li>
  • Средние подстраницы- (пронумерованы, чтобы установить порядок сортировки в формате html так же, как родительская страница) <li>sub page #</li>
  • Последняя подстраница в группе - должна заканчиваться </ul>

Ответы [ 2 ]

4 голосов
/ 29 апреля 2011

Я хочу, чтобы xsl приравнял это к следующему: если это подстраница, добавьте к элементу тег ul, а если это последняя подстраница под родителем, добавьте закрывающий тег ul.

Ты думаешь не так. XSLT не пишет теги, он пишет дерево узлов. Вы не можете записать половину узла в дерево результатов.

В XSLT 2.0 вы, вероятно, можете делать то, что вы хотите, используя xsl: for-each-group с атрибутом group-начиная-с - я не могу быть конкретным, потому что вы не указали проблему достаточно четко, но это наверное как то так:

<xsl:template match="parent">
  <xsl:for-each-group select="*" group-starting-with="li[....]">
    <ul>
      <xsl:copy-of select="current-group()"/>
    </ul>
  </xsl:for-each-group>
</xsl:template>

Если вы застряли с XSLT 1.0, тогда это будет сложнее: я бы использовал технику, называемую «рекурсия брата», в которой вы применяете шаблоны к первому дочернему элементу, который, в свою очередь, применяет шаблоны к следующему брату и скоро. Шаблонное правило для родителя делает это:

<xsl:template match="parent">
  <xsl:apply-templates select="*[1]"/>
</xsl:template>

Шаблонное правило для родного брата, который должен быть первым в группе, делает это:

<xsl:template match="parent/*[ (: where this is the first in a group :) ]">
  <group>
    <xsl:copy-of select="."/>
    <xsl:apply-templates select="following-sibling::*[1]"/>
  </group>
  <xsl:apply-templates select="following-sibling::*[(* start of next group *)][1]"/>
</xsl:template>

и шаблонное правило для других братьев и сестер:

<xsl:template match="parent/*">
  <xsl:copy-of select="."/>
  <xsl:apply-templates select="following-sibling::*[1]"/>
</xsl:template>

Детали могут быть хитрыми даже для опытных разработчиков XSLT.

0 голосов
/ 28 апреля 2011

Я что-то упустил.Поскольку XSL - это документ XML, который можно использовать для преобразования другого документа XML (XHTML, SOAP и т. Д.) В другой формат, который обычно представляет собой некоторый XML.Если вы подаете документ данных (строку и т. Д.) В XSL, он преобразуется в соответствии с установленным вами шаблоном, который должен быть действительным XML.

Теперь, почему это проблема в вашем случае.Вы только строите часть структуры и затем добавляете ее к другой части, пока не получите целое?Если это так, я бы собрал все биты в один фрагмент данных (файл, строку и т. Д.) И запустил преобразование для него.Или оставьте местозаполнители на самом высоком уровне, добавьте соответствующие метки в конец и добавьте дочерние биты таким образом.

Глядя на ваш вопрос, я вижу, что вы хотите один действительный и один недействительный, что заставляет меня верить, что выпытаясь найти решение по частям.К сожалению, я не знаю, как сказать XSL: «Эй, это неверный XML, но не волнуйтесь».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...