2012-04-19 2 views
1

В настоящее время я работаю над скриптом XSL, который преобразует следующий xml в упорядоченный список. Пожалуйста, обратитесь к образцу ввода и вывода ниже. Кстати, я использую XSLT 2.0.Преобразование списка XSLT

**Input:** 
<xml> 
    <numberedList>1. Number List 1</numberedList> 
    <unnumberedList>Child List 1</unnumberedList> 
    <unnumberedList>Child List 2</unnumberedList> 
    <unnumberedList>Child List 3</unnumberedList> 
    <numberedList>2. Number List 2</numberedList> 
    <unnumberedList>Child List 1</unnumberedList> 
    <numberedList>3. Number List 3</numberedList> 
</xml> 

**Output:** 
<html> 
<ol> 
    <li>1. Number List 1</li> 
    <li> 
     <ul> 
      <li>Child List 1</li> 
      <li>Child List 2</li> 
      <li>Child List 3</li> 
     </ul> 
    </li> 
    <li>2. Number List 2</li> 
    <li> 
     <ul> 
      <li>Child List 1</li> 
     </ul> 
    </li> 
    <li>3. Number List 3</li> 
</ol> 
</html> 

Любая помощь была бы принята с благодарностью. Благодаря!

+0

Является ли это домашнее задание? что ты уже испробовал? –

+0

Привет, Роб, я пробовал использовать с групповым смешением, но это не будет делать трюк. –

ответ

3

Покушение улучшения на XSLT решения Dimitre в 2.0:

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

<xsl:template match="/*"> 
    <html> 
    <ol> 
    <xsl:for-each-group select="*" group-adjacent="name()"> 
     <xsl:choose> 
     <xsl:when test="self::numberedList"> 
      <xsl:apply-templates select="current-group()"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <li><ul><xsl:apply-templates select="current-group()"/></ul></li> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each-group> 
    </ol> 
    </html> 
</xsl:template> 

<xsl:template match="numberedList|unnumberedList"> 
    <li><xsl:apply-templates/></li> 
</xsl:template> 

</xsl:stylesheet> 
+0

Я мог бы написать это так, если бы я не хотел создавать код «if-less». Я считаю, что устранение явных условий (хотя иногда приходится использовать способы для достижения этого) способствует читабельности и понятности. Конечно, мой подход можно считать экстремальным, и это решение показывает, что при экономном использовании условные выражения могут создавать «естественные» решения. –

+0

+1 за хороший ответ. –

+0

Большое спасибо за решения ребята! Я ценю это. Все они работали бы чудесно, но я предпочитаю самое короткое решение. –

0

Несомненно, это можно сделать проще, но попробуйте следующее.
Пояснение: это самоочевидно :-)
Обратите внимание, что это также будет работать в XSLT 1.0.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="xml"> 
     <html> 
      <ol> 
       <xsl:apply-templates select="numberedList[1]"/> 
      </ol> 
     </html> 
    </xsl:template> 
    <xsl:template match="numberedList"> 
     <li> 
      <xsl:value-of select="."/> 
     </li> 
     <xsl:apply-templates select="following-sibling::*[1]"/> 
    </xsl:template> 
    <xsl:template match="unnumberedList [local-name(preceding-sibling::*[1]) = 'numberedList']"> 
     <li> 
      <ul> 
       <li> 
        <xsl:value-of select="."/> 
       </li> 
       <xsl:apply-templates select="following-sibling::*[1] [local-name() = 'unnumberedList']"/> 
      </ul> 
     </li> 
     <xsl:apply-templates select="following-sibling::numberedList[1]"/> 
    </xsl:template> 
    <xsl:template match="unnumberedList [local-name(preceding-sibling::*[1]) = 'unnumberedList']"> 
     <li> 
      <xsl:value-of select="."/> 
     </li> 
     <xsl:apply-templates select="following-sibling::*[1] [local-name() = 'unnumberedList']"/> 
    </xsl:template> 
</xsl:stylesheet> 

Что дает следующий результат:

<?xml version="1.0" encoding="UTF-8"?> 
<html> 
    <ol> 
     <li>1. Number List 1</li> 
     <li> 
      <ul> 
       <li>Child List 1</li> 
       <li>Child List 2</li> 
       <li>Child List 3</li> 
      </ul> 
     </li> 
     <li>2. Number List 2</li> 
     <li> 
      <ul> 
       <li>Child List 1</li> 
      </ul> 
     </li> 
     <li>3. Number List 3</li> 
    </ol> 
</html> 
2

I. немного короче XSLT 1.0 решение:

<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="kUlist" match="unnumberedList" 
    use="generate-id(preceding-sibling::* 
         [not(self::unnumberedList)][1] 
        )"/> 

<xsl:template match="/*"> 
    <html> 
    <xsl:apply-templates select="numberedList[1]" mode="first"/> 
    </html> 
</xsl:template> 

<xsl:template match="numberedList" mode="first"> 
    <ol> 
    <xsl:apply-templates select=". | following-sibling::*"/> 
    </ol> 
</xsl:template> 

<xsl:template match="*"> 
    <li><xsl:apply-templates /></li> 
</xsl:template> 

<xsl:template match= 
"unnumberedList 
     [not(preceding-sibling::*[1][self::unnumberedList])]"> 
    <li> 
    <ul> 
     <xsl:apply-templates mode="inUList" select= 
      "key('kUlist', generate-id(preceding-sibling::*[1]))"/> 
    </ul> 
    </li> 
</xsl:template> 

<xsl:template match="*" mode="inUList"> 
    <li><xsl:value-of select="."/></li> 
</xsl:template> 
<xsl:template match="unnumberedList"/> 
</xsl:stylesheet> 

, когда это преобразование применяется на прилагаемом документе XML:

<xml> 
    <numberedList>1. Number List 1</numberedList> 
    <unnumberedList>Child List 1</unnumberedList> 
    <unnumberedList>Child List 2</unnumberedList> 
    <unnumberedList>Child List 3</unnumberedList> 
    <numberedList>2. Number List 2</numberedList> 
    <unnumberedList>Child List 1</unnumberedList> 
    <numberedList>3. Number List 3</numberedList> 
</xml> 

разыскиваемых, правильный результат получается:

<html> 
    <ol> 
     <li>1. Number List 1</li> 
     <li> 
     <ul> 
      <li>Child List 1</li> 
      <li>Child List 2</li> 
      <li>Child List 3</li> 
     </ul> 
     </li> 
     <li>2. Number List 2</li> 
     <li> 
     <ul> 
      <li>Child List 1</li> 
     </ul> 
     </li> 
     <li>3. Number List 3</li> 
    </ol> 
</html> 

II. XSLT 2.0, раствор - 30% короче, чем И.

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

<xsl:template match="/*"> 
    <html> 
    <ol> 
    <xsl:for-each-group select="*" group-adjacent="name()"> 
     <xsl:apply-templates select="current-group()"/> 
    </xsl:for-each-group> 
    </ol> 
    </html> 
</xsl:template> 

<xsl:template match="*" mode="#default inUList"> 
    <li><xsl:apply-templates/></li> 
</xsl:template> 

<xsl:template match= 
    "unnumberedList[preceding-sibling::*[1][not(self::unnumberedList)]]"> 
    <li> 
    <ul> 
    <xsl:apply-templates mode="inUList" select="current-group()"/> 
    </ul> 
    </li> 
</xsl:template> 
<xsl:template match="unnumberedList"/> 
</xsl:stylesheet> 

когда это XSLT-преобразование 2.0 применяется на том же самом документе XML (выше), то же правильный результат получается:

<html> 
    <ol> 
     <li>1. Number List 1</li> 
     <li> 
     <ul> 
      <li>Child List 1</li> 
      <li>Child List 2</li> 
      <li>Child List 3</li> 
     </ul> 
     </li> 
     <li>2. Number List 2</li> 
     <li> 
     <ul> 
      <li>Child List 1</li> 
     </ul> 
     </li> 
     <li>3. Number List 3</li> 
    </ol> 
</html> 
Смежные вопросы