我有这个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('<', '/ul', '>')" />
<xsl:value-of disable-output-escaping="yes" select="concat('<', '/div', '>')" />
有趣的是,IE10可以解决这个问题,但Firefox无法正确呈现它。
答案 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>
希望这有帮助。