XSL:将 xml 转换为排序的多列 html 表

发布于 2024-10-29 07:58:39 字数 2890 浏览 1 评论 0原文

我正在看一个类似于此处涵盖的问题

转换列表进入二维表

但有轻微的皱纹。我的XML没有任何特定顺序,我想对其进行排序以显示。例如,我的XML是

<items>  
  <item>A</item>  
  <item>C</item>  
  <item>E</item>  
  <item>B</item>  
  <item>D</item> 
  <!-- ... any number of item nodes ... -->
<item>  

,我希望我的输出是(出于说明目的而忽略了非命名节点的地方)

<table>
    <tr>
        <td>A</td>
        <td>C</td>
        <td>E</td>
    </tr>
    <tr>
        <td>B</td>
        <td>D</td>
        <td />
    </tr>
</table>

XSL我依据的XSL来自上述链接(我需要使用XSL 1.0):

<xsl:template match="/*">
    <table>
        <xsl:call-template name="make-columns">
            <xsl:with-param name="nodelist" select="item"/>
        </xsl:call-template>
    </table>
</xsl:template>

<xsl:template name="make-columns">
    <xsl:param name="nodelist"/>
    <xsl:param name="columns-number" select="3"/>

    <tr>
        <xsl:apply-templates select="$nodelist[
                        not(position() > $columns-number)
                        ]"/>
        <xsl:if test="count($nodelist) &lt; $columns-number">
            <xsl:call-template name="empty-cells">
                <xsl:with-param name="finish" 
                                select="$columns-number - count($nodelist)"/>
            </xsl:call-template>
        </xsl:if>
    </tr>

    <!-- If some nodes are left, recursively call current
    template, passing only nodes that are left -->
    <xsl:if test="count($nodelist) > $columns-number">
        <xsl:call-template name="make-columns">
            <xsl:with-param name="nodelist" select="$nodelist[
                                    position() > $columns-number
                                    ]"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template match="item">
    <td>
        <xsl:apply-templates/>
    </td>
</xsl:template>

<xsl:template name="empty-cells">
    <xsl:param name="finish"/>
    <td/>
    <xsl:if test="not($finish = 1)">
        <xsl:call-template name="empty-cells">
            <xsl:with-param name="finish" select="$finish - 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

我尝试在各种应用程序中插入命令,但这无效。

想法?

杰夫

评论更新

我想输出一个多列表 有 3 列,其中条目是 按字母顺序垂直

I am looking at a similar problem to what was covered here

Transforming List into a 2-D Table

but with a slight wrinkle. My XML is not in any particular order and I would like to sort it for display. For example my XML is

<items>  
  <item>A</item>  
  <item>C</item>  
  <item>E</item>  
  <item>B</item>  
  <item>D</item> 
  <!-- ... any number of item nodes ... -->
<item>  

and I want my output to be (where I am ignoring the non-named nodes for illustrative purposes)

<table>
    <tr>
        <td>A</td>
        <td>C</td>
        <td>E</td>
    </tr>
    <tr>
        <td>B</td>
        <td>D</td>
        <td />
    </tr>
</table>

The XSL I am basing this off is from the above link (I need to use XSL 1.0):

<xsl:template match="/*">
    <table>
        <xsl:call-template name="make-columns">
            <xsl:with-param name="nodelist" select="item"/>
        </xsl:call-template>
    </table>
</xsl:template>

<xsl:template name="make-columns">
    <xsl:param name="nodelist"/>
    <xsl:param name="columns-number" select="3"/>

    <tr>
        <xsl:apply-templates select="$nodelist[
                        not(position() > $columns-number)
                        ]"/>
        <xsl:if test="count($nodelist) < $columns-number">
            <xsl:call-template name="empty-cells">
                <xsl:with-param name="finish" 
                                select="$columns-number - count($nodelist)"/>
            </xsl:call-template>
        </xsl:if>
    </tr>

    <!-- If some nodes are left, recursively call current
    template, passing only nodes that are left -->
    <xsl:if test="count($nodelist) > $columns-number">
        <xsl:call-template name="make-columns">
            <xsl:with-param name="nodelist" select="$nodelist[
                                    position() > $columns-number
                                    ]"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template match="item">
    <td>
        <xsl:apply-templates/>
    </td>
</xsl:template>

<xsl:template name="empty-cells">
    <xsl:param name="finish"/>
    <td/>
    <xsl:if test="not($finish = 1)">
        <xsl:call-template name="empty-cells">
            <xsl:with-param name="finish" select="$finish - 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

I have tried inserting commands within the various apply-templates but that doesn't work.

ideas?

Jeff

Update from comments

I want to output a multicolum table
with 3 columns where the entries are
in alphabetical order vertically

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

给妤﹃绝世温柔 2024-11-05 07:58:39

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
  exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pNumCols" select="3"/>

 <xsl:variable name="vNumRows" select=
      "ceiling(count(/*/*) div $pNumCols)"/>

 <xsl:variable name="vrtfSorted">
   <xsl:for-each select="/*/*">
    <xsl:sort/>
    <xsl:copy-of select="."/>
   </xsl:for-each>
 </xsl:variable>

 <xsl:variable name="vSorted"
      select="ext:node-set($vrtfSorted)/*"/>

 <xsl:template match="/">
  <table>
   <xsl:apply-templates select=
     "$vSorted[not(position() > $vNumRows)]"/>
  </table>
 </xsl:template>

 <xsl:template match="item">
  <tr>
   <xsl:apply-templates select=
   "(.|following-sibling::*[position() mod $vNumRows =0])/text()"/>
  </tr>
 </xsl:template>

 <xsl:template match="text()">
  <td><xsl:value-of select="."/></td>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<items>
    <item>A</item>
    <item>C</item>
    <item>E</item>
    <item>B</item>
    <item>D</item>
</items>

产生所需的正确结果:

<table>
  <tr>
    <td>A</td>
    <td>C</td>
    <td>E</td>
  </tr>
  <tr>
    <td>B</td>
    <td>D</td>
  </tr>
</table>

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
  exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pNumCols" select="3"/>

 <xsl:variable name="vNumRows" select=
      "ceiling(count(/*/*) div $pNumCols)"/>

 <xsl:variable name="vrtfSorted">
   <xsl:for-each select="/*/*">
    <xsl:sort/>
    <xsl:copy-of select="."/>
   </xsl:for-each>
 </xsl:variable>

 <xsl:variable name="vSorted"
      select="ext:node-set($vrtfSorted)/*"/>

 <xsl:template match="/">
  <table>
   <xsl:apply-templates select=
     "$vSorted[not(position() > $vNumRows)]"/>
  </table>
 </xsl:template>

 <xsl:template match="item">
  <tr>
   <xsl:apply-templates select=
   "(.|following-sibling::*[position() mod $vNumRows =0])/text()"/>
  </tr>
 </xsl:template>

 <xsl:template match="text()">
  <td><xsl:value-of select="."/></td>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<items>
    <item>A</item>
    <item>C</item>
    <item>E</item>
    <item>B</item>
    <item>D</item>
</items>

produces the wanted, correct result:

<table>
  <tr>
    <td>A</td>
    <td>C</td>
    <td>E</td>
  </tr>
  <tr>
    <td>B</td>
    <td>D</td>
  </tr>
</table>
若言繁花未落 2024-11-05 07:58:39

更新:现在,解释了新的要求,此样式表:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
    <xsl:strip-space elements="*"/>
    <xsl:param name="pColumns" select="3"/>
    <xsl:template match="items">
        <xsl:variable name="vrtfChilds">
            <xsl:for-each select="*">
                <xsl:sort/>
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="vChilds" select="msxsl:node-set($vrtfChilds)/*"/>
        <xsl:variable name="vRows" 
                      select="ceiling(count($vChilds) div $pColumns)"/>
        <table>
            <xsl:for-each select="$vChilds[$vRows >= position()]">
                <tr>
                    <xsl:call-template name="columns">
                        <xsl:with-param name="pRows" select="$vRows"/>
                    </xsl:call-template>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
    <xsl:template name="columns">
        <xsl:param name="pData" select="."/>
        <xsl:param name="pColumn" select="$pColumns"/>
        <xsl:param name="pRows" select="0"/>
        <xsl:if test="$pColumn">
            <td>
                <xsl:apply-templates select="$pData"/>
            </td>
            <xsl:call-template name="columns">
                <xsl:with-param name="pData"
                     select="$pData/following-sibling::*[$pRows]"/>
                <xsl:with-param name="pColumn" select="$pColumn - 1"/>
                <xsl:with-param name="pRows" select="$pRows"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

输出:

<table>
    <tr>
        <td>A</td>
        <td>C</td>
        <td>E</td>
    </tr>
    <tr>
        <td>B</td>
        <td>D</td>
        <td></td>
    </tr>
</table>

注意:用于两阶段转换的node-set扩展函数。

Update: Now, with new requeriment explained, this stylesheet:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 exclude-result-prefixes="msxsl">
    <xsl:strip-space elements="*"/>
    <xsl:param name="pColumns" select="3"/>
    <xsl:template match="items">
        <xsl:variable name="vrtfChilds">
            <xsl:for-each select="*">
                <xsl:sort/>
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="vChilds" select="msxsl:node-set($vrtfChilds)/*"/>
        <xsl:variable name="vRows" 
                      select="ceiling(count($vChilds) div $pColumns)"/>
        <table>
            <xsl:for-each select="$vChilds[$vRows >= position()]">
                <tr>
                    <xsl:call-template name="columns">
                        <xsl:with-param name="pRows" select="$vRows"/>
                    </xsl:call-template>
                </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
    <xsl:template name="columns">
        <xsl:param name="pData" select="."/>
        <xsl:param name="pColumn" select="$pColumns"/>
        <xsl:param name="pRows" select="0"/>
        <xsl:if test="$pColumn">
            <td>
                <xsl:apply-templates select="$pData"/>
            </td>
            <xsl:call-template name="columns">
                <xsl:with-param name="pData"
                     select="$pData/following-sibling::*[$pRows]"/>
                <xsl:with-param name="pColumn" select="$pColumn - 1"/>
                <xsl:with-param name="pRows" select="$pRows"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Output:

<table>
    <tr>
        <td>A</td>
        <td>C</td>
        <td>E</td>
    </tr>
    <tr>
        <td>B</td>
        <td>D</td>
        <td></td>
    </tr>
</table>

Note: node-set extension function for a two phase transformation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文