Xml 如何在XSLT的前一个同级中测试多个条件

Xml 如何在XSLT的前一个同级中测试多个条件,xml,xslt,lotus-notes,Xml,Xslt,Lotus Notes,我有从传统LotusNotes应用程序中提取的XML数据,并嵌入了richtext格式。我试图根据前一个同级中出现的属性格式化每个文本块。我从@Jayvee获得了XSLT的灵感,但它不起作用 这是XML: <?xml version="1.0" encoding="UTF-8"?> <document> <item name="Unordered list"> <richtext> <parde

我有从传统LotusNotes应用程序中提取的XML数据,并嵌入了richtext格式。我试图根据前一个同级中出现的属性格式化每个文本块。我从@Jayvee获得了XSLT的灵感,但它不起作用

这是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>
    
    
    /保险商实验室
    /ol
    保险商实验室
    ol
    

  • 上一个问题中的方法使用
    禁用输出转义
    来输出开始和结束标记,这不是一种理想的方法

    相反,考虑使用一个键将第一个前面的<代码> PAR < /COD>元素组合在一起,代码<>代码> DEF属性

    <xsl:key name="pars" 
             match="par[not(@def)]" 
             use="generate-id(preceding-sibling::par[@def][1])" />
    
    要确定是否将组包装在
    ul
    ol
    标记中,您可以获得如下列表类型:

    <xsl:variable name="listType" select="preceding-sibling::*[1][self::pardef]/@list" />
    
    
    
    然后,您可以对此进行测试,以确定是否将组包装在列表标记中

    试试这个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>
    
    
    

  • 上一个问题中的方法使用
    禁用输出转义
    来输出开始和结束标记,这不是一种理想的方法

    相反,考虑使用一个键将第一个前面的<代码> PAR < /COD>元素组合在一起,代码<>代码> DEF属性

    <xsl:key name="pars" 
             match="par[not(@def)]" 
             use="generate-id(preceding-sibling::par[@def][1])" />
    
    要确定是否将组包装在
    ul
    ol
    标记中,您可以获得如下列表类型:

    <xsl:variable name="listType" select="preceding-sibling::*[1][self::pardef]/@list" />
    
    
    
    然后,您可以对此进行测试,以确定是否将组包装在列表标记中

    试试这个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>
    
    
    

  • 您的解决方案非常优雅,可以使用我提供的XML代码片段。但在我在这里简化的真实XML中,键不起作用,因为大多数段落都有def属性。我需要在清单声明中匹配所有的PAR节点,其中DEF属性与PARDEF的ID属性相匹配。听起来您可能需要问一个新问题;您的解决方案非常优雅,并且可以使用我使用的XML片段