14

我正在使用带有以下 xsl 标头的 xalan:

<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"/>

并且输出没有缩进。

有想法的人吗?

4

5 回答 5

23

对于缩进,您需要使用不同的命名空间:(http://xml.apache.org/xslt请参阅此问题

<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"/>
于 2011-03-26T16:28:11.360 回答
13

一直在为此苦苦挣扎,但只是意外地工作了:

关键是添加<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="*"/>

不知道为什么,但可能删除所有空格有助于 xalan 找出缩进

于 2013-04-18T16:11:45.993 回答
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。

于 2011-05-30T18:15:56.383 回答
2

我想你必须设置methodto 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"/>
于 2010-03-08T15:14:20.777 回答
1

虽然这是一个相当古老的问题,但答案可能还有另一个尚未触及的角度。

ResultTL; DR 重要的是它的味道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定义命名空间,也不需要一个strip-space元素来工作(如果你尝试在输入文档,缩进空格只是添加到它们,这看起来很傻,所以你可以选择使用strip-space,但缩进发生在任何一种方式)。

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

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>

所以“howout”对于缩进是否发生很重要。这些方法是什么?

嗯,Java 不只有一个 API 用于处理 XML。它有几个,包括 DOM、StAX 和 SAX,更不用说您可能只想将 XML 处理为,或通过/String的字符流,或通过Reader/Writer的编码字节流。InputStreamOutputStream

JDBC 规范指出,如果您正在编写 Java 代码以在数据库中使用 XML,SQLXML API必须让您选择任何一种处理数据的方式,以方便您的任务。JAXP 转换 API 说您必须能够处理Transformer几乎任何风格的Source. Result,并让它做正确的事情。

所以这就是为什么那些 PL/Java 示例函数有“how”参数的原因:需要有一种方法来测试可以将相同 XML 内容传递给的所有必需方式以及可以返回 's 结果Transformer的所有方式。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

那么相同的 xalan 缩进变换在以不同的方式调用以产生其结果时会做什么呢?

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>

嗯,这就是模式。对于Transformer 实际上必须直接生成字符或字节的序列化流的所有 API ,它会根据要求添加缩进。

当它被赋予SAXResult, StAXResult, 或DOMResult写入时,它不会添加缩进,因为这些都是结构化的 XML API;就好像 xalan 将缩进严格视为一个序列化问题,从技术上讲,它在生成 SAX、StAX 或 DOM 时并没有序列化。

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

因此,如果您发现自己试图让 xalan 转换来进行缩进,但事实并非如此,请仔细检查Result您要求Transformer生成哪种形式。

编辑:最后一点:如果您直接在 Java 中进行编码,那么实际上根本不需要编写那些七行 XSLT 来获得无非是具有indent输出属性集的身份转换。

如果你调用 no-argument TransformerFactory.newTransformer(),它会直接你一个普通的身份转换。然后你需要做的就是设置它的输出属性,然后你就开始做生意了:

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);

没有比这更简单的了。同样,重要的result是 a StreamResult,以便转换器进行序列化。

于 2020-03-10T00:49:41.293 回答