在XSLT中打开和关闭HTML标记

时间:2013-05-28 11:19:13

标签: html xml xslt tags

我有这个XML:

    <XmlTreff IsSub="false" Start="false" Stop="false">
      <Id>Id0</Id>
      <Tittel>Title0</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="false" Start="false" Stop="false">
      <Id>Id1</Id>
      <Tittel>Title1</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="true" Stop="false">
      <Id>Id2</Id>
      <Tittel>Title2</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="false">
      <Id>Id3</Id>
      <Tittel>Title3</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="true">
      <Id>Id4</Id>
      <Tittel>Title4</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="false" Start="false" Stop="false">
      <Id>Id5</Id>
      <Tittel>Title5</Tittel>
    </XmlTreff>

此XML使用XSLT进行转换,并应生成此HTML

<html>
    <body>
        <div>
            <div>
                <a href="doesntmatter">Title0</a>
            </div>
            <div>
                <a href="doesntmatter">Title1</a>
            </div>
            <ul>
                <li>
                    <a href="doesntmatter">Title2</a>
                </li>
                <li>
                    <a href="doesntmatter">Title3</a>
                </li>
                <li>
                    <a href="doesntmatter">Title4</a>
                </li>
            </ul>
            <div>
                <a href="doesntmatter">Title5</a>
            </div>
        </div>
    </body>
</html>

我们的想法是Start,Stop和IsSub属性控制着标签的打开和关闭。

目前我有这个XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/XmlSokeResultat/Treff">
        <html xmlns="http://www.w3.org/1999/xhtml" lang="no" xml:lang="no">
            <body>
                <xsl:for-each select="XmlTreff">
                    <div class="XmlTreffinfo">
                        <xsl:if test="@IsSub = 'false'">                               
                            <div>
                                <div>
                                    <xsl:element name="a">
                                        <xsl:value-of select="Tittel"/>
                                    </xsl:element>
                                </div>
                            </div>
                        </xsl:if>

                        <xsl:if test="@Start = 'true'">
                            <div>
                              <ul>
                        </xsl:if>

                        <xsl:if test="@IsSub = 'true'">
                          <ul>
                          <li>                                    
                            <a>
                              <xsl:value-of select="."/>
                            </a>
                          </li>
                          </ul>
                        </xsl:if>

                        <xsl:if test="@Stop = 'true'">
                              </ul>
                            </div>
                        </xsl:if>
                    </div>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

问题是不允许在语法错误的地方使用开始和结束标记。你知道怎么解决这个问题吗? (请参阅ifs,其中起始div和ul放置在与结束标记不同的位置)

编辑:我可以在XML中添加和删除属性,但元素结构必须是这样的吗?

EDIT2:我尝试使用concat和value-of

渲染HTML标记
   <xsl:value-of disable-output-escaping="yes" select="concat('&lt;', '/ul', '&gt;')" />
   <xsl:value-of disable-output-escaping="yes" select="concat('&lt;', '/div', '&gt;')" />

有趣的是,IE10可以解决这个问题,但Firefox无法正确呈现它。

4 个答案:

答案 0 :(得分:1)

我建议使用基于密钥的解决方案将XmlTreff元素分组。

<xsl:key name="kChildren" match="XmlTreff[@IsSub='true']"
              use="generate-id(preceding-sibling::XmlTreff[@IsSub='false'][1])"/>

而不是使用以下模板:

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="kChildren" match="XmlTreff[@IsSub='true']"
              use="generate-id(preceding-sibling::XmlTreff[@IsSub='false'][1])"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="XmlTreff[@IsSub = 'false']" >
        <div>
            <a href="doesntmatter">
                <xsl:value-of select="Tittel"/>
            </a>
        </div>
        <ul>
            <xsl:apply-templates select="key('kChildren', generate-id())" />
        </ul>

    </xsl:template>
    <xsl:template match="XmlTreff[@IsSub = 'true']"  >
        <li>
            <a href="doesntmatter">
                <xsl:value-of select="Tittel"/>
            </a>
        </li>
    </xsl:template>
    <xsl:template match="/*" >

        <html>
            <body>
                <div class="XmlTreffinfo">
                    <xsl:apply-templates select="XmlTreff[@IsSub = 'false']" />
                </div>
            </body>
        </html>

    </xsl:template>
</xsl:stylesheet>

注意:我忽略了Start和Stop属性。唯一的意思可能是首先提示最后一个条目。

使用此输入: ?xml version =“1.0”encoding =“utf-8”?&gt;

<xml>
    <XmlTreff IsSub="false" Start="false" Stop="false">
        <Id>Id1</Id>
        <Tittel>Title1</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="true" Stop="false">
        <Id>Id2</Id>
        <Tittel>Title2</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="false">
        <Id>Id3</Id>
        <Tittel>Title3</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="true">
        <Id>Id4</Id>
        <Tittel>Title4</Tittel>
    </XmlTreff>

    <XmlTreff IsSub="false" Start="false" Stop="false">
        <Id>Id1</Id>
        <Tittel>Title12</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="true" Stop="false">
        <Id>Id2</Id>
        <Tittel>Title22</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="false">
        <Id>Id3</Id>
        <Tittel>Title32</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="true">
        <Id>Id4</Id>
        <Tittel>Title42</Tittel>
    </XmlTreff>
</xml>

它将生成以下输出:

<?xml version="1.0"?>
<html>
  <body>
    <div class="XmlTreffinfo">
      <div>
        <a href="doesntmatter">Title1</a>
      </div>
      <ul>
        <li>
          <a href="doesntmatter">Title2</a>
        </li>
        <li>
          <a href="doesntmatter">Title3</a>
        </li>
        <li>
          <a href="doesntmatter">Title4</a>
        </li>
      </ul>
      <div>
        <a href="doesntmatter">Title12</a>
      </div>
      <ul>
        <li>
          <a href="doesntmatter">Title22</a>
        </li>
        <li>
          <a href="doesntmatter">Title32</a>
        </li>
        <li>
          <a href="doesntmatter">Title42</a>
        </li>
      </ul>
    </div>
  </body>
</html>

答案 1 :(得分:0)

您的问题是以正确和简单的方式使用XSLT的一个很好的例子。它可以使用三个模板来解决。您不需要启动和停止属性:

<?xml version="1.0" encoding="UTF-8"?>  
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
    <html>
        <body>
            <div>
                <xsl:apply-templates select="//XmlTreff[@IsSub='false']"/>
            </div>
            <ul>
                <xsl:apply-templates select="//XmlTreff[@IsSub='true']"/>
            </ul>
        </body>
    </html>
</xsl:template>
<xsl:template match="XmlTreff[@IsSub='false']">
    <div>
        <a href="doesntmatter">
            <xsl:value-of select="Tittel"/>
        </a>
    </div>
</xsl:template>
<xsl:template match="XmlTreff[@IsSub='true']">
    <li>
        <a href="doesntmatter">
            <xsl:value-of select="Tittel"/>
        </a>
    </li>
</xsl:template>
</xsl:stylesheet>  

抱歉@ hr_117:我只看到了那么多的代码,并没有意识到你的解决方案与我的解决方案大致相同,只是为了简单起见我没有使用密钥

答案 2 :(得分:-1)

如果启动和停止不匹配怎么办?我认为这是一项毫无希望的任务,说实话。要么让XML直接具有结构,如:

<XmlTreff>
    <Id>Id1</Id>
    <Tittel>Title1</Tittel>
    <XmlTreff>
        <Id>Id2</Id>
        <Tittel>Title2</Tittel>
    </XmlTreff>
    <XmlTreff>
        <Id>Id3</Id>
        <Tittel>Title3</Tittel>
    </XmlTreff>
    <XmlTreff>
        <Id>Id4</Id>
        <Tittel>Title4</Tittel>
    </XmlTreff>
</XmlTreff>

或者,如果您不能这样做,请在单独的部分中定义结构,例如,使用Id标记值来引用您的项目。

<structure>
    <item idref="Id1">
        <item idref="Id2" />
        <item idref="Id3" />
        <item idref="Id4" />
    </item>
</structure>

答案 3 :(得分:-1)

我编写了一个稍微复杂的示例版本,以确保我完全运用您的模型:

<document>
    <XmlTreff IsSub="false" Start="false" Stop="false">
        <Id>Id0</Id>
        <Tittel>Title0</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="false" Start="false" Stop="false">
        <Id>Id1</Id>
        <Tittel>Title1</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="true" Stop="false">
        <Id>Id2</Id>
        <Tittel>Title2</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="false">
        <Id>Id3</Id>
        <Tittel>Title3</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="true">
        <Id>Id4</Id>
        <Tittel>Title4</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="false" Start="false" Stop="false">
        <Id>Id5</Id>
        <Tittel>Title5</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="true" Stop="false">
        <Id>Id6</Id>
        <Tittel>Title6</Tittel>
    </XmlTreff>
    <XmlTreff IsSub="true" Start="false" Stop="false">
        <Id>Id7</Id>
        <Tittel>Title7</Tittel>
    </XmlTreff>
</document>

然后使用模式并复制以下子序列,以下XSLT将解析您的元素:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:template match="/">
        <html>
            <body>
                <div>
                    <xsl:apply-templates select="*"/>                    
                </div>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="XmlTreff[@IsSub='false']">
        <div>
            <xsl:apply-templates select="." mode="link"/>
        </div>
    </xsl:template>

    <xsl:template match="XmlTreff" mode="link">
        <a href="doesntmatter"><xsl:value-of select="Tittel"/></a>       
    </xsl:template>

    <xsl:template match="XmlTreff[@IsSub='false' or preceding-sibling::XmlTreff[@IsSub='false']]" mode="toFirstFalse"/>

    <xsl:template match="XmlTreff[not(@IsSub='false') and not(preceding-sibling::XmlTreff[@IsSub='false'])]" mode="toFirstFalse">
        <xsl:copy-of select="."/>
    </xsl:template>

    <xsl:template match="XmlTreff[@IsSub='true' and not(preceding-sibling::XmlTreff[1][@IsSub='true'])]">
        <xsl:variable name="following">
            <xsl:copy-of select="following-sibling::XmlTreff"/>
        </xsl:variable>
        <xsl:variable name="subset">
            <xsl:apply-templates select="$following" mode="toFirstFalse"/>
        </xsl:variable>

        <ul>
            <xsl:apply-templates select="(.|$subset)" mode="children"/>
        </ul>
    </xsl:template>

    <xsl:template match="XmlTreff" mode="children">
        <li>
            <xsl:apply-templates select="." mode="link"/>
        </li>
    </xsl:template>

    <xsl:template match="XmlTreff[@IsSub='true' and preceding-sibling::XmlTreff[1][@IsSub='true']]"/>


</xsl:stylesheet>

进入以下结果:

<html>
   <body>
      <div>

         <div><a href="doesntmatter">Title0</a></div>

         <div><a href="doesntmatter">Title1</a></div>

         <ul>
            <li><a href="doesntmatter">Title2</a></li>
            <li><a href="doesntmatter">Title3</a></li>
            <li><a href="doesntmatter">Title4</a></li>
         </ul>



         <div><a href="doesntmatter">Title5</a></div>

         <ul>
            <li><a href="doesntmatter">Title6</a></li>
            <li><a href="doesntmatter">Title7</a></li>
         </ul>


      </div>
   </body>
</html>

希望这有帮助。