如何在XSLT中自动换行?

时间:2014-02-17 10:49:53

标签: xml xslt xslt-1.0

我使用XSLT从XML中提取数据。我想在xml-editor中查看数据。如何将文本换行以适应XSLT中的窗口?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:template match='/'>
        <wawes> 
            <xsl:for-each select="//VARIABLE">
                <xsl:sort select="@ID" order="descending"/>
                <wave>  
                    <id>  
                        <xsl:value-of select="@ID" ></xsl:value-of>    
                    </id>
                    <NAME>
                        <xsl:value-of select="NAME"/>
                    </NAME> 
                </wave>      
            </xsl:for-each>
        </wawes>          
    </xsl:template> 

</xsl:stylesheet>

3 个答案:

答案 0 :(得分:0)

为了适应屏幕大小或分辨率而环绕文本通常与XSLT无关。 XSLT只关注转换XML,而不关心XML数据的表示和布局。

如果您认为这不是太糟糕:所有类型的屏幕尺寸,分辨率以及所有类型的应用程序(包括XML编辑器)都必须同样可以访问相同的XML。将XML与这三个因素的独特组合(窗口大小怎么样?)放在一起是很冒昧的。

相反,正如@rene指出的那样,包装文本几乎是每个文本编辑器的一个功能。例如,在UltraEdit中有 CTRL + W

N.b。在技​​术上不可能在XSLT中强制包装文本。您可以在元素的文本内容中引入换行符。但

  • 他们的渲染取决于您的应用程序。 XML编辑器很可能来渲染它们。
  • 目前还不清楚 究竟应该引入它们,因为在“转换时间”你无法知道哪些屏幕,窗口和应用程序将访问XML数据

答案 1 :(得分:0)

我的其他答案使用XSLT-2提供了解决方案,而此问题的初始范围为XSLT-1

这个前提是基于这样的想法:反复重复目标字符串,切掉可变大小的子50段并将每个段放在它自己的行上,然后继续这个功能,直到没有更多的文本可用。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:user="http://www.altova.com/MapForce/UDF/user" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="user xs">
    <xsl:template name="user:FindLastSpace">
        <xsl:param name="text" select="/.."/>
        <xsl:variable name="var1_resultof_string_length" select="string-length($text)"/>
        <xsl:variable name="var4_result">
            <xsl:choose>
                <xsl:when test="string(('0' = $var1_resultof_string_length)) != 'false'">
                    <xsl:value-of select="'0'"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="var2_resultof_substring" select="substring($text, $var1_resultof_string_length)"/>
                    <xsl:variable name="var3_result">
                        <xsl:value-of select="($var2_resultof_substring = ' ')"/>
                        <xsl:value-of select="($var2_resultof_substring = ',')"/>
                    </xsl:variable>
                    <xsl:choose>
                        <xsl:when test="string(boolean(translate(normalize-space($var3_result), 'false0 ', ''))) != 'false'">
                            <xsl:value-of select="$var1_resultof_string_length"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:call-template name="user:FindLastSpace">
                                <xsl:with-param name="text" select="substring($text, '1', ($var1_resultof_string_length - '1'))"/>
                            </xsl:call-template>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:value-of select="floor($var4_result)"/>
    </xsl:template>
    <xsl:template name="user:CrLf">
        <xsl:value-of select="'&#x0A;'"/>
    </xsl:template>
    <xsl:template name="user:FormLines">
        <xsl:param name="remainingText" select="/.."/>
        <xsl:param name="length" select="/.."/>
        <xsl:variable name="var1_resultof_substring" select="substring($remainingText, '1', $length)"/>
        <xsl:variable name="var2_resultof_FindLastSpace">
            <xsl:call-template name="user:FindLastSpace">
                <xsl:with-param name="text" select="$var1_resultof_substring"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="var4_result">
            <xsl:choose>
                <xsl:when test="string(($var2_resultof_FindLastSpace = '0')) != 'false'">
                    <xsl:variable name="var3_resultof_string_length" select="string-length($remainingText)"/>
                    <xsl:value-of select="$var3_resultof_string_length"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="user:FindLastSpace">
                        <xsl:with-param name="text" select="$var1_resultof_substring"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="var5_resultof_CrLf">
            <xsl:call-template name="user:CrLf"/>
        </xsl:variable>
        <xsl:variable name="var6_resultof_FindLastSpace">
            <xsl:call-template name="user:FindLastSpace">
                <xsl:with-param name="text" select="$var1_resultof_substring"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="var8_result">
            <xsl:choose>
                <xsl:when test="string(($var6_resultof_FindLastSpace = '0')) != 'false'">
                    <xsl:variable name="var7_resultof_string_length" select="string-length($remainingText)"/>
                    <xsl:value-of select="$var7_resultof_string_length"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="user:FindLastSpace">
                        <xsl:with-param name="text" select="$var1_resultof_substring"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="var11_result">
            <xsl:choose>
                <xsl:when test="string((substring($remainingText, ($var8_result + '1')) = '')) != 'false'">
                    <xsl:value-of select="''"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="var9_resultof_FindLastSpace">
                        <xsl:call-template name="user:FindLastSpace">
                            <xsl:with-param name="text" select="$var1_resultof_substring"/>
                        </xsl:call-template>
                    </xsl:variable>
                    <xsl:variable name="var10_result">
                        <xsl:choose>
                            <xsl:when test="string(($var9_resultof_FindLastSpace = '0')) != 'false'">
                                <xsl:value-of select="string-length($remainingText)"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:call-template name="user:FindLastSpace">
                                    <xsl:with-param name="text" select="$var1_resultof_substring"/>
                                </xsl:call-template>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:variable>
                    <xsl:call-template name="user:FormLines">
                        <xsl:with-param name="remainingText" select="substring($remainingText, ($var10_result + '1'))"/>
                        <xsl:with-param name="length" select="$length"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:value-of select="concat(concat(substring($remainingText, '1', $var4_result), $var5_resultof_CrLf), $var11_result)"/>
    </xsl:template>
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <xformResult>
            <xsl:call-template name="user:FormLines">
                <xsl:with-param name="remainingText" select="'Google HQ, 345 Spear St, San Francisco, Foo, Bar, Baz, 012310123'"/>
                <xsl:with-param name="length" select="floor('50')"/>
            </xsl:call-template>
        </xformResult>
    </xsl:template>
</xsl:stylesheet>

在许多测试中都能很好地工作。请原谅我的疯狂,我把它扔在MapForce中

答案 2 :(得分:-1)

使用正则表达式使用XSLT-2的{​​{1}}函数(替换为replace)来分解字符串,我取得了相当的成功。我知道你关注$1\n,但是从我发现的情况来看,正则表达式是没有迭代解析的唯一方法。

最初,我发现this question and answer,但是我无法让它在XSLT允许的正则表达式子集中工作,主要是由于缺乏积极的前瞻而受阻。

虽然XSLT是关于XML操作的,但我的工作已经证明,这不是唯一的用例,因为我们使用XSLT来执行大规模数据转换以实现系统和客户端的互操作性,不仅仅是XML数据,还有纯文本和格式化文本(即CSV)数据。

一个这样的转变需要一组地址元素的内爆:

XSLT-1

进入一个类似于:

的文本块
<Address>
    <Name>Google HQ</Name>
    <Line1>345 Spear St</Line1>
    <Line2></Line2>
    <Line3></Line3>
    <Line4></Line4>
    <City>San Francisco</City>
    <PostCode>94105</PostCode>
    <County>CA</County>
    <Country>United States</Country>
    <CountryCode>USA</CountryCode>
</Address>

但是,此信息将被放入的字段仅限于4行,每行为50个字符。为了节省空间,我将Google HQ, 345 Spear St, San Francisco, 94105, CA, USA PostCodeCounty放在一行并单独添加,因此我有3行50个字符。然后我拿走剩余的字段,并将它们一起CSV(除非一个是空白的),这样看起来像:

  

Google HQ,345 Spear St,San Francisco

看看我上面提到的问题和答案,我得到了正则表达式(交换长度为16的50):

CountryCode

但是,它在XSLT中不起作用。

对于初学者来说,它不会识别(?:((?>.{1,50}(?:(?<=[^\S\r\n])[^\S\r\n]?|(?=\r?\n)|$|[^\S\r\n]))|.{1,50})(?:\r?\n)?|(?:\r?\n|$)) (原子组)或(?>(正向前瞻,但在与匿名组交换后,它可以正常工作。

但在那之后,我得到了与零长度字符串匹配的错误。这是由(?=的最后一次出现引起的,这导致它与行尾匹配,但没有它,它最终起作用。它并不像我希望的那样整洁,但它确实将单行文本压缩成一组每行都小于50个字符的行。最后的正则表达式是:

|$

现在,在我不适合你的情况下,我也有线路限制,但我只是丢弃了其余的线路。

希望对你有所帮助