【问题标题】:How do I make xsl transformation indent the output?如何使 xsl 转换缩进输出?
【发布时间】:2011-01-25 00:34:49
【问题描述】:

我正在使用带有以下 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"/>

而且输出没有缩进。

有人有想法吗?

【问题讨论】:

  • 我在notepad++中使用了xsl工具。当我的 xsl 中有错字时,它无法缩进输出。验证您的 xsl 文件具有正确的语法。

标签: xslt indentation xalan


【解决方案1】:

我猜你必须将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"/>

【讨论】:

  • 是否有可能您正在使用无法正确呈现内容的应用程序查看 xml?
【解决方案2】:

对于缩进,您需要使用不同的命名空间: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"/>

【讨论】:

【解决方案3】:

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。

【讨论】:

    【解决方案4】:

    为此苦苦挣扎了一段时间,但意外地让它工作了:

    关键是添加&lt;xsl:strip-space elements="*"/&gt;

    所以它看起来像这样:

    <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 找出缩进

    【讨论】:

    • 如果没有xsl:strip-space[@elements="*"],xsl 会尝试在输出中保留输入中的空白节点。
    • 即使没有 xalan 也能像魅力一样工作 :)
    【解决方案5】:

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

    TL;DR 重要的是 ResultTransformer 的味道。(如果您通过 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 不只有一种用于处理 XML 的 API。它有几个,包括 DOM、StAX 和 SAX,更不用说您可能只想将 XML 处理为 String,或通过 Reader/Writer 处理字符流,或通过 @987654340 处理编码字节流@/OutputStream.

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

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

     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,它会根据要求添加缩进。

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

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

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

    编辑: 最后一点:如果您是直接用 Java 编写代码,那么真的根本不需要编写那些七行代码的 XSLT 来获得仅此而已带有indent 输出属性集的身份转换。

    如果您调用无参数 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 必须是 StreamResult,以便转换器进行序列化。

    【讨论】:

      猜你喜欢
      • 2011-05-17
      • 1970-01-01
      • 2014-07-19
      • 2012-08-03
      • 1970-01-01
      • 1970-01-01
      • 2020-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多