2010-06-30 3 views
1

У меня есть следующий XML-данные:Создание динамического HTML таблицы с XSL

<Activity> 
<ObjectGroup type="default"> 
<Object id="1874" name="PR1010Date" type="reference label" index="10" columnNo="0" dynamic="true"> 
     <Description>Date</Description>  
     <Value instance="0">30/06/2010</Value> 
    </Object> 
    <Object id="1875" name="PR1020LoggedBy" type="reference label" index="20" columnNo="1" dynamic="true"> 
     <Description>Request Logged By</Description>  
     <Value>Site Administrator</Value> 
    </Object> 
    <Object id="1876" name="PR1030Comments" type="large text box" index="30" columnNo="0" dataType="Text"> 
     <Description>Comments</Description>  
     <Value instance="0">Test</Value> 
    </Object> 
<ObjectGroup> 
</Activity> 

Мне нужно создать XSL, который будет производить следующий вывод:

<html> 
<table> 
<tr> 
<td width="50%">30/06/2010</td> 
<td width="50%">Site Admin</td> 
</tr> 
<tr> 
<td width="100%">Test</td> 
</tr> 
</table> 

В приведенном выше XML-атрибута индекс наряду с диском columnNo количество строк и столбцов генерируется. Что конечный результат определяется в столбце No, поэтому, если в ObjectGroup есть объекты с инкрементным столбцомNo, то они все отображаются в одну строку с соответствующей шириной для каждого столбца.

+0

И что вы получили до сих пор? Где у вас возникают трудности? Люди здесь не будут делать вашу работу за вас. – Oded

+0

Маленький в сторону, но ваш HTML не будет отображаться правильно; установка ширины до 100% не приведет к тому, что она будет охватывать два столбца, вам нужно указать 'colspan =" 2 "'. – Flynn1179

+0

Хороший вопрос (+1). См. Мой ответ для полного и эффективного решения. –

ответ

1

Это преобразование:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:key name="kObjByCol" match="Object" 
    use="@columnNo"/> 

<xsl:key name="kRow" match="Object[@columnNo != 0]" 
    use="generate-id(preceding-sibling::Object 
           [@columnNo = 0][1] 
        )"/> 

<xsl:template match="/*"> 
    <html> 
    <table border="1"> 
     <xsl:apply-templates select= 
     "key('kObjByCol', 0)"/> 
    </table> 
    </html> 
</xsl:template> 

<xsl:template match="Object"> 
    <xsl:variable name="vcellNodes" 
    select=".|key('kRow',generate-id())"/> 
    <tr> 
    <xsl:apply-templates mode="row" select= 
     "$vcellNodes"> 
     <xsl:with-param name="pCount" 
      select="count($vcellNodes)"/> 
    </xsl:apply-templates> 
    </tr> 
</xsl:template> 

<xsl:template match="Object" mode="row"> 
    <xsl:param name="pCount"/> 
    <td width="{100 div $pCount}%"> 
    <xsl:value-of select="Value"/> 
    </td> 
</xsl:template> 
</xsl:stylesheet> 

при применении к предоставленному документу XML (корректируется, чтобы быть хорошо сформирован):

<Activity> 
    <ObjectGroup type="default"> 
     <Object id="1874" name="PR1010Date" 
     type="reference label" index="10" 
     columnNo="0" dynamic="true"> 
      <Description>Date</Description> 
      <Value instance="0">30/06/2010</Value> 
     </Object> 
     <Object id="1875" name="PR1020LoggedBy" 
     type="reference label" index="20" 
     columnNo="1" dynamic="true"> 
      <Description>Request Logged By</Description> 
      <Value>Site Administrator</Value> 
     </Object> 
     <Object id="1876" name="PR1030Comments" 
     type="large text box" index="30" 
     columnNo="0" dataType="Text"> 
      <Description>Comments</Description> 
      <Value instance="0">Test</Value> 
     </Object> 
    </ObjectGroup> 
</Activity> 

производит желаемое, правильный результат:

<html> 
    <table border="1"> 
     <tr> 
      <td width="50%">30/06/2010</td> 
      <td width="50%">Site Administrator</td> 
     </tr> 
     <tr> 
      <td width="100%">Test</td> 
     </tr> 
    </table> 
</html> 
1

После отличной отклика от Dimitre, другой таблицы стилей без ключей.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:template match="ObjectGroup"> 
     <html> 
      <table border="1"> 
       <xsl:apply-templates select="Object[@columnNo=0]"/> 
      </table> 
     </html> 
    </xsl:template> 
    <xsl:template match="Object"> 
     <xsl:variable name="td" 
         select=".|following-sibling::*[@columnNo!=0][ 
             count(current()| 
              preceding-sibling::*[@columnNo=0][1] 
            )=1]"/> 
     <tr> 
      <xsl:apply-templates select="$td/Value"> 
       <xsl:with-param name="td-count" select="count($td)"/> 
      </xsl:apply-templates> 
     </tr> 
    </xsl:template> 
    <xsl:template match="Value"> 
     <xsl:param name="td-count"/> 
     <td width="{100 div $td-count}%"> 
      <xsl:value-of select="."/> 
     </td> 
    </xsl:template> 
</xsl:stylesheet> 

Однако большинство XSLT-процессоров позволяют использовать ключи.

Теперь для Colspan:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:variable name="td-max"> 
     <xsl:call-template name="max"> 
      <xsl:with-param name="nodes" select="/*/*/Object[@columnNo=0]"/> 
     </xsl:call-template> 
    </xsl:variable> 
    <xsl:template name="max"> 
     <xsl:param name="nodes"/> 
     <xsl:if test="$nodes"> 
      <xsl:variable name="head" 
           select="count($nodes[1]/following-sibling::*[@columnNo!=0][ 
              count($nodes[1]| 
               preceding-sibling::*[@columnNo=0][1] 
             )=1])+1"/> 
      <xsl:variable name="tail"> 
       <xsl:call-template name="max"> 
        <xsl:with-param name="nodes" select="$nodes[position() > 1]"/> 
       </xsl:call-template> 
      </xsl:variable> 
      <xsl:choose> 
       <xsl:when test="$head > $tail or $tail=''"> 
        <xsl:value-of select="$head"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="$tail"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:if> 
    </xsl:template> 
    <xsl:template match="ObjectGroup"> 
     <html> 
      <table border="1"> 
       <xsl:apply-templates select="Object[@columnNo=0]"/> 
      </table> 
     </html> 
    </xsl:template> 
    <xsl:template match="Object"> 
     <xsl:variable name="td" 
          select=".|following-sibling::*[@columnNo!=0][ 
              count(current()| 
               preceding-sibling::*[@columnNo=0][1] 
             )=1]"/> 
     <tr> 
      <xsl:apply-templates select="$td/Value"> 
       <xsl:with-param name="td-count" select="count($td)"/> 
      </xsl:apply-templates> 
     </tr> 
    </xsl:template> 
    <xsl:template match="Value"> 
     <xsl:param name="td-count"/> 
     <td width="{100 div $td-count}%"> 
      <xsl:if test="position()=last() and $td-max > $td-count"> 
       <xsl:attribute name="colspan"> 
        <xsl:value-of select="$td-max - $td-count + 1"/> 
       </xsl:attribute> 
      </xsl:if> 
      <xsl:value-of select="."/> 
     </td> 
    </xsl:template> 
</xsl:stylesheet> 

Редактировать: Добавлен динамический Объединение столбцов. Он может быть менее подробным, если вам не все равно, colspan="1".

Редактировать 2: Лучше всего образец.

+0

Спасибо за ответы. Таблица стилей, предоставленная Димитрием, помогла мне и указала мне в правильном направлении. – Manthan

+0

@Manthan: Вы хорошо! Кроме того, я должен сказать, что вы должны отметить пост «Димитрия» как правильный ответ, чтобы помочь другим. – 2010-07-02 03:15:55

+0

@Dimitre: Есть ли способ, чтобы я мог рассчитать colspan для строк, ширина которых будет равна 100%, так что HTML будет отображаться правильно, как в настоящее время, когда я использую 100% в качестве ширины для строк с только одним столбцом, который он ставит HTML все в порядке. Возможно ли в пределах таблицы стилей, что я могу пересекать вывод xslt на более позднем этапе, чтобы я мог настроить colspan строк только с одним столбцом. – Manthan

Смежные вопросы