简体   繁体   English

在XSLT中打开和关闭HTML标签

[英]Opening and closing HTML tag in XSLT

I have this XML: 我有这个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>

This XML is transformed with XSLT and should produce this HTML 该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>

The thought was that the attributes Start, Stop, and IsSub controls the opening and closing of the tags. 想法是,属性Start,Stop和IsSub控制着标签的打开和关闭。

Currently i have this XSLT: 目前我有这个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>

The problem is that having opening and closing tags in a syntactical wrong place is not allowed. 问题是不允许在语法错误的位置打开和关闭标签。 Do you know how to solve this? 你知道如何解决吗? (See inside the ifs where the starting div and ul are placed at different place than the closing tags) (请参阅ifs内部的起始div和ul与结束标记位于不同的位置)

EDIT: I can add and remove attributes to the XML, but the element structure must be like this? 编辑:我可以添加和删除XML的属性,但元素结构必须是这样的?

EDIT2: I have tried to render out the HTML tags using concat and value-of 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;')" />

Interestingly, IE10 can handle this and but Firefox is not able to render it out correctly. 有趣的是,IE10可以处理此问题,但是Firefox无法正确呈现它。

I would suggest a key based solution to group you XmlTreff elements. 我建议基于密钥的解决方案将XmlTreff元素分组。

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

And than use templates as following: 然后使用如下模板:

<?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>

Attention: I ignore the Start and Stop attribute. 注意:我忽略“开始”和“停止”属性。 Only meaning for this could be to have a hint for first an last entry. 这样做的唯一含义可能是提示先输入最后输入。

With this input: ?xml version="1.0" encoding="utf-8" ?> 输入以下内容:?xml version =“ 1.0” encoding =“ utf-8”吗?>

<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>

It will generate following output: 它将生成以下输出:

<?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>

Your problem is a great example to use XSLT in a proper and simple way. 您的问题是一个以适当且简单的方式使用XSLT的好例子。 It can be solved using three templates. 可以使用三个模板来解决。 You don't need start and stop attributes: 您不需要开始和停止属性:

<?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>  

Sorry @hr_117: I only saw that amount of code and did not realize that your solution is about the same as mine except I did not use keys for simplicity 抱歉,@ hr_117:我只看到了那么多的代码,却没有意识到您的解决方案与我的解决方案大致相同,只是为了简单起见我没有使用键

What if the starts and stops doesnt match up? 如果启动和停止不匹配怎么办? I think this is a hopeless task, to be honest. 老实说,我认为这是一项绝望的任务。 Either make your XML have the structure directly, as in: 使您的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>

or, if you cannot do that, define the structure in a separate section, where you refer to your items with, for instance, the Id tag value. 或者,如果不能这样做,请在单独的部分中定义结构,在该部分中,您将使用Id标记值引用您的商品。

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

I made up a slightly more complex version of your example to make sure I exercise your model completely: 我为您的示例制作了一个稍微复杂些的版本,以确保我完全行使您的模型:

<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>

Then using modes and copy for following subsequences the following XSLT will parse out your elements: 然后,使用mode并复制以下子序列,以下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>

Into the following result: 变成以下结果:

<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>

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM