[英]How to calculate max string-length of a node-set?
我正在嘗試使用XSLT將XML文檔轉換為純文本表供人類使用。 我正在使用xsltproc
,它僅實現XSLT 1.0(所以max
實際上來自EXSLT)。
我嘗試了以下操作,但注釋掉的定義失敗,因為string-length
僅返回單個值( 第一個節點的字符串值的長度),而不是max
想要的節點集。
轉型:
<?xml version="1.0" encoding="utf-8"?>
<!-- vim: set sts=2 sw=2: -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math" xmlns:str="http://exslt.org/strings">
<xsl:output method="text"/>
<xsl:template match="/root">
<!-- <xsl:variable name="max_a_width" select="math:max(string-length(data/@a))"/> -->
<xsl:variable name="max_a_width" select="string-length(data/@a)"/>
<xsl:text>+-</xsl:text><xsl:value-of select="str:padding($max_a_width, '-')"/><xsl:text>-+ </xsl:text>
<xsl:for-each select="data">
<xsl:text>| </xsl:text><xsl:value-of select="@a"/><xsl:value-of select="str:padding($max_a_width - string-length(@a), ' ')"/><xsl:text> | </xsl:text>
</xsl:for-each>
<xsl:text>+-</xsl:text><xsl:value-of select="str:padding($max_a_width, '-')"/><xsl:text>-+ </xsl:text>
</xsl:template>
</xsl:stylesheet>
輸入:
<?xml version="1.0" encoding="utf-8"?>
<!-- vim: set sts=2 sw=2: -->
<root>
<data a="aa"/>
<data a="aaa"/>
<data a="a"/>
</root>
輸出:
+----+
| aa |
| aaa |
| a |
+----+
為了使右邊界對齊,我需要在變量中具有實際的最大值。 (在我的實際示例中,我將具有列標題和多列,但是重現該問題不是必需的)。
如果可以更輕松地找到解決方案,則可以保證數據值永遠不會包含空格。
<xsl:variable name="max_a_width">
<xsl:for-each select="data">
<xsl:sort select="string-length(@a)" data-type="number" />
<xsl:if test="position() = last()">
<xsl:value-of select="string-length(@a)" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
這是從XSLT 1.0中的派生值的有序列表中進行選擇的通用方法。
如果要從實際(可排序的本地)值中選擇最小值/最大值,則可以采用以下捷徑:
<xsl:variable name="max_a" select="//a[not(. < //a)][1]" />
這是一個簡單的遞歸模板。 使用與輸入相同的XSLT文件運行它以對其進行測試。 使用XSLT 2或XQuery當然更容易...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template name="maxlen"> <xsl:param name="input" /> <xsl:param name="max-so-far" select="0" /> <xsl:choose> <xsl:when test="not($input)"> <xsl:value-of select="$max-so-far" /> </xsl:when> <xsl:when test="string-length($input[1]) > $max-so-far"> <xsl:call-template name="maxlen"> <xsl:with-param name="input" select="$input[position() > 1]" /> <xsl:with-param name="max-so-far" select="string-length($input[1])" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:call-template name="maxlen"> <xsl:with-param name="input" select="$input[position() > 1]" /> <xsl:with-param name="max-so-far" select="$max-so-far" /> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:variable name="input"> <test> <string>123456789012345678901234</string> <string>12345678901234</string> <string>1234567890</string> <string>12345678901234567890123456</string> </test> </xsl:variable> <xsl:template match="/"> <output> <xsl:call-template name="maxlen"> <xsl:with-param name="input" select="//test/string" /> </xsl:call-template> </output> </xsl:template> </xsl:stylesheet>
這是使用EXSLT math:max()
執行此操作的方法:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:math="http://exslt.org/math"
xmlns:str="http://exslt.org/strings">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/root">
<xsl:variable name="lengths">
<xsl:for-each select="data">
<length><xsl:value-of select="string-length(@a)"/></length>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="max_a_width" select="math:max(exsl:node-set($lengths)/length)"/>
<!-- the rest -->
</xsl:template>
</xsl:stylesheet>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.