如何在XSLT中的前一个同级中测试多个条件 [英] How to test for multiple conditions in previous-sibling in XSLT

查看:61
本文介绍了如何在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">&lt;/ul&gt;</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">&lt;/ol&gt;</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">&lt;ul&gt;</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">&lt;ol&gt;</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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆