如何在XSLT中的前一个同级中测试多个条件 [英] How to test for multiple conditions in previous-sibling in XSLT
问题描述
我有从旧版Lotus Notes应用程序中提取的XML数据,并且具有嵌入式RTF格式.我正在尝试根据上一个同级中出现的属性来格式化每个文本块.我的XSLT受@Jayvee的此响应的启发但它不起作用.
I have XML data that was extracted from a legacy Lotus Notes application and that has embedded richtext formatting. I am trying to format each block of text based on attributes that appear in a previous sibling. I have XSLT inspired by this response from @Jayvee but it's not working.
这是XML:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<item name="Unordered list">
<richtext>
<pardef/>
<par def="20">
<run>This is the first </run><run>paragraph of the preamble.</run>
</par>
<par>
<run>This is the second paragraph of the </run><run>preamble.</run>
</par>
<pardef id="21" list="unordered"/>
<par def="21">
<run>This is the </run><run>first bullet.</run>
</par>
<par>
<run>This is the second </run><run>bullet.</run>
</par>
<par def="20">
<run>This is the first </run><run>paragraph of the conclusion.</run>
</par>
<par>
<run>This is the second paragraph of the </run><run>conclusion.</run>
</par>
</richtext>
</item>
<item name="Ordered list">
<richtext>
<pardef/>
<par def="20">
<run>This is the first </run><run>paragraph of the preamble.</run>
</par>
<par>
<run>This is the second paragraph of the </run><run>preamble.</run>
</par>
<pardef id="46" list="ordered"/>
<par def="46">
<run>This is the </run><run>first numbered item.</run>
</par>
<par>
<run>This is the another </run><run>numbered item.</run>
</par>
<par def="20">
<run>This is the first </run><run>paragraph of the conclusion.</run>
</par>
<par>
<run>This is the second paragraph of the </run><run>conclusion.</run>
</par>
</richtext>
</item>
</document>
这是所需的输出:
<html>
<body>
<table border="1">
<tr>
<td>Unordered list</td>
<td>
<p>This is the first paragraph of the preamble.</p>
<p>This is the second paragraph of the preamble.</p>
<ul>
<li>This is the first bullet.</li>
<li>This is the second bullet.</li>
</ul>
<p>This is the first paragraph of the conclusion.</p>
<p>This is the second paragraph of the conclusion.</p>
</td>
</tr>
<tr>
<td>Ordered list</td>
<td>
<p>This is the first paragraph of the preamble.</p>
<p>This is the second paragraph of the preamble.</p>
<ol>
<li>This is the first numbered item.</li>
<li>This is the another numbered item.</li>
</ol>
<p>This is the first paragraph of the conclusion.</p>
<p>This is the second paragraph of the conclusion.</p>
</td>
</tr>
</table>
</body>
这是XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/*">
<html>
<body>
<table border="1">
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<tr>
<td><xsl:value-of select="@name"/></td>
<td>
<xsl:apply-templates/>
</td>
</tr>
</xsl:template>
<xsl:template match="par">
<xsl:choose>
<xsl:when test="preceding-sibling::pardef[@list] = 'unordered' and preceding-sibling::par[@def][1][@def] != preceding-sibling::pardef[@id]"><xsl:text disable-output-escaping="yes"></ul></xsl:text></xsl:when>
<xsl:when test="preceding-sibling::pardef[@list] = 'ordered' and preceding-sibling::par[@def][1][@def] != preceding-sibling::pardef[@id]"><xsl:text disable-output-escaping="yes"></ol></xsl:text></xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="@def=preceding-sibling::pardef[@id] or (not(@def) and preceding-sibling::par[@def][1][@def=preceding-sibling::pardef[@id]])">
<xsl:choose>
<xsl:when test="preceding-sibling::pardef[@list] = 'unordered' and preceding-sibling::par[@def][1][@def] = preceding-sibling::pardef[@id]"><xsl:text disable-output-escaping="yes"><ul></xsl:text></xsl:when>
<xsl:when test="preceding-sibling::pardef[@list] = 'ordered' and preceding-sibling::par[@def][1][@def] = preceding-sibling::pardef[@id]"><xsl:text disable-output-escaping="yes"><ol></xsl:text></xsl:when>
</xsl:choose>
<li>
<xsl:for-each select="run">
<xsl:value-of select="text()" separator=""/>
</xsl:for-each>
</li>
</xsl:when>
<xsl:when test="not(@def=preceding-sibling::pardef[@id])">
<p>
<xsl:for-each select="run">
<xsl:value-of select="text()" separator=""/>
</xsl:for-each>
</p>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
推荐答案
上一个问题中的方法使用disable-output-escaping
输出开始和结束标签,这不是理想的方法.
The approach in the previous question use disable-output-escaping
to output the start and end tags, which is not an ideal approach.
相反,请考虑使用键将第一个前面的带有def
属性的par
元素组合在一起par
元素
Instead, consider using a key to group together par
elements by the first preceding par
element with a def
attribute
<xsl:key name="pars"
match="par[not(@def)]"
use="generate-id(preceding-sibling::par[@def][1])" />
并且,假设您在par
元素上匹配了def
属性,则可以像这样使用键:
And, assuming you are matched on a par
element a def
attribute, you can use the key like so:
<xsl:variable name="group" select="self::* | key('pars', generate-id())" />
要确定是将组包装在ul
还是ol
标记中,可以按如下所示获取列表类型:
To work out whether to wrap the group in an ul
or ol
tag, you can possibly get the list type as follows:
<xsl:variable name="listType" select="preceding-sibling::*[1][self::pardef]/@list" />
然后您可以对此进行测试,以确定是否将组包装在列表标记中.
You can then test this to determine whether to wrap the group in a list tag.
尝试使用此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:key name="pars" match="par[not(@def)]" use="generate-id(preceding-sibling::par[@def][1])" />
<xsl:template match="/*">
<html>
<body>
<table border="1">
<xsl:apply-templates />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<tr>
<td><xsl:value-of select="@name"/></td>
<td>
<xsl:apply-templates select="richtext/par[@def]" />
</td>
</tr>
</xsl:template>
<xsl:template match="par[@def]">
<xsl:variable name="listType" select="preceding-sibling::*[1][self::pardef]/@list" />
<xsl:variable name="group" select="self::* | key('pars', generate-id())" />
<xsl:choose>
<xsl:when test="$listType = 'unordered'">
<ol>
<xsl:apply-templates select="$group" mode="list"/>
</ol>
</xsl:when>
<xsl:when test="$listType = 'ordered'">
<ul>
<xsl:apply-templates select="$group" mode="list"/>
</ul>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="$group" mode="para" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="par" mode="list">
<li>
<xsl:value-of select="run" separator=""/>
</li>
</xsl:template>
<xsl:template match="par" mode="para">
<para>
<xsl:value-of select="run" separator=""/>
</para>
</xsl:template>
</xsl:stylesheet>
这篇关于如何在XSLT中的前一个同级中测试多个条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!