如何使xsl转换缩进输出?

时间:2010-03-08 15:05:11

标签: xslt indentation xalan

我正在使用xalan和以下xsl标头:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0"
    xmlns:redirect="http://xml.apache.org/xalan/redirect"
    extension-element-prefixes="redirect"
    xmlns:xalan="http://xml.apache.org/xalan">
<xsl:output method="text" indent="yes" xalan:indent-amount="4"/>

输出没有缩进。

有想法的人吗?

5 个答案:

答案 0 :(得分:21)

对于缩进,您需要使用不同的命名空间:“http://xml.apache.org/xslt”(请参阅​​this issue

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:redirect="http://xml.apache.org/xalan/redirect"
extension-element-prefixes="redirect"
xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml" indent="yes" xalan:indent-amount="4"/>

答案 1 :(得分:9)

暂时挣扎了一段时间,但是让它意外地工作了:

关键是要添加<xsl:strip-space elements="*"/>

所以看起来像这样:

<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:java="http://xml.apache.org/xalan/java"
    xmlns:xalan="http://xml.apache.org/xslt">
<xsl:output method="xml" encoding="ASCII" indent="yes" xalan:indent-amount="4"/>
<xsl:strip-space elements="*"/>

不确定原因,但可能删除所有whitespacing有助于xalan找出缩进

答案 2 :(得分:5)

Jirka-x1,谢谢你的问题链接。我使用了以下内容(由Ed Knoll 13 / Aug / 04提出):

<xsl:stylesheet ... xmlns:xslt="http://xml.apache.org/xslt">
<xsl:output ... indent="yes" xslt:indent-amount="4" />

这适用于xalan(java)2.7.1。

答案 3 :(得分:2)

我想你必须将method设置为xml。如果这不起作用,请尝试以下操作:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xalan">

<xsl:output method="xml" encoding="UTF-8" indent="yes" xalan:indent-amount="4"/>

答案 4 :(得分:0)

虽然这是一个很老的问题,但答案上可能还有另一个尚未涉及的角度。

TL; DR与Result注入的Transformer的味道很重要。(如果您通过Java代码使用xalan,则不会编写/可以没变化,这可能不是您想听到的。)

对于此答案中的演示,我将使用PostgreSQL PL / Java,因为它附带了一组示例函数,包括preparexmltransformtransformxml,这些函数使用Java的基于xalan的XSLT 1.0,并有一些额外的参数用于测试目的。没有这些额外的参数,我不会看到一个重要的行为影响。

我将从准备一个名为indent的转换开始:

SELECT
 preparexmltransform(
  'indent',
  '<xsl:transform version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
     <xsl:copy-of select="."/>
    </xsl:template>
   </xsl:transform>',
  how => 5);

应该足够清楚,第一个参数是转换的名称,第二个参数是定义转换的XSLT。我将稍后讨论“如何”的论点。

因此,无论如何,让我们在某些XML上使用该转换,看看会发生什么:

SELECT
  transformxml(
   'indent',
   '<a b="c" d="e"><f><g/><h/></f></a>',
   howin => 5, howout => 4);

  transformxml
----------------
<a b="c" d="e">
    <f>
        <g/>
        <h/>
    </f>
</a>

很酷,可以立即完成所需的操作,并表明上面的简短转换就足够了;值得注意的是,它不需要xalan:indent-amount属性(除非您喜欢不同的缩进宽度),因此它不需要定义xalan命名空间,也不必{{{ 1}}元素可以正常工作(如果您尝试在输入文档中使用空格,则仅向其中添加缩进空格,看起来有些愚蠢,因此您可能选择以使用{{1} },但缩进会以任何一种方式发生。

我还没有说这些额外的参数做什么(现在是它们中的两个,“ howin”和“ howout”!),但是这即将到来,因为看起来发生了什么,除了“ howout”从4变为5:

strip-space

因此,“缩进”对于缩进是否发生很重要。这些怎么样?

嗯,Java并不只有一个用于处理XML的API。它有多个,包括DOM,StAX和SAX,更不用说您可能只想将XML处理为strip-space或通过SELECT transformxml( 'indent', '<a b="c" d="e"><f><g/><h/></f></a>', howin => 5, howout => 5); transformxml ------------------------------------ <a b="c" d="e"><f><g/><h/></f></a> / String处理字符流,或者将通过Reader / Writer编码的字节流。

JDBC规范规定,如果您要编写Java代码以在数据库中使用XML,SQLXML API必须为您提供使用这些数据的任何方式的选择,以您方便的方式为准任务。而且JAXP Transformations API指出,您必须能够将InputStreamOutputStream的任何口味的Transformer传递给您,并使其正确地工作。

这就是为什么这些PL / Java示例函数具有“如何”参数的原因:需要一种方法来测试将相同XML内容可以传递给Source的所有必需方法以及Result的结果可以返回。 “方式”是这样(任意)排列的:

Transformer

当用不同的方式产生结果时,相同的xalan缩进转换又会做什么呢?

Transformer

嗯,有模式。对于实际上 code | form | howin | howout ------+---------------------+--------------+-------------- 1 | binary stream | InputStream | OutputStream 2 | character stream | Reader | Writer 3 | String | String | String 4 | binary or character | StreamSource | StreamResult 5 | SAX | SAXSource | SAXResult 6 | StAX | StAXSource | StAXResult 7 | DOM | DOMSource | DOMResult 实际上必须直接产生字符或字节序列化流的所有API ,它都会按要求添加缩进。

当给它一个SELECT i, transformxml( 'indent', '<a b="c" d="e"><f><g/><h/></f></a>', howin => 5, howout => i) FROM generate_series(1,7) AS i; i | transformxml ---+------------------------------------------ 1 | <a b="c" d="e"> | <f> | <g/> | <h/> | </f> | </a> | 2 | <a b="c" d="e"> | <f> | <g/> | <h/> | </f> | </a> | 3 | <a b="c" d="e"> | <f> | <g/> | <h/> | </f> | </a> | 4 | <a b="c" d="e"> | <f> | <g/> | <h/> | </f> | </a> | 5 | <a b="c" d="e"><f><g/><h/></f></a> 6 | <a b="c" d="e"><f><g></g><h></h></f></a> 7 | <a b="c" d="e"><f><g/><h/></f></a> TransformerSAXResult进行写入时,它不会添加缩进,因为它们都是结构化XML API。好像xalan严格将缩进视为序列化问题,并且在生产SAX,StAX或DOM时,从技术上讲,它不是序列化

(上表还显示,当其他API进行操作时,StAX API并不总是将空元素呈现为自关闭状态。附带问题,但很有趣。)

因此,如果您发现自己试图进行xalan转换以进行缩进,但并非如此,请仔细检查您要求StAXResult产生哪种形式的DOMResult

编辑:最后一点:如果您直接用Java编写代码,那么实际上根本不需要编写XSLT的那七行代码,仅仅是为了得到什么而已。设置了Result输出属性的身份转换。

如果您调用无参数TransformerFactory.newTransformer(),它会直接给您 一个普通的身份转换。然后,您需要做的就是设置其输出属性,然后您就可以从事业务:

Transformer

没有比这更简单的了。同样,将indent设为var tf = javax.xml.transform.TransformerFactory.newInstance(); var t = tf.newTransformer(); t.setOutputProperty("indent", "yes"); t.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "1"); // if you don't like the default 4 t.transform(source, result); 至关重要,这样转换器才能进行序列化。