关于JAXP,XSLT和XML保留字符

时间:2014-05-22 08:38:01

标签: xml xslt jaxp

看起来JAXP允许为文档节点分配任何值,包括<,>和&和别的。使用XML保留字符和XSLT引发了一个问题。请考虑以下代码:

DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();

...

Element field = doc.createElement("col");
field.setTextContent( "<p>&]]" );
row.appendChild( field );

...

TransformerFactory factory = TransformerFactory.newInstance();
Source xslt = new StreamSource(new File("templateName.xsl"));
Transformer transformer = factory.newTransformer(xslt);

transformer.transform( new DOMSource(doc), new StreamResult(printer) );

现在,如果我们有

<xsl:value-of select="col" disable-output-escaping="yes"/>

在&#34; templateName.xsl&#34;中,输出看起来像

"<p>&]]"

如果我们有这个

<xsl:value-of select="col"/>

输出将是

&lt;p&gt;&amp;]]

基本上我的问题是,JAXP使用什么样的内部数据表示这样

"<p>&]]"

可以吗?它不能是文本节点,也不能是CDATA节点。它是什么?我相信必须有一个为转换提供的有效XML文档。另一方面,disable-output-escaping属性表示特殊字符应按原样输出,是否意味着我们的&#34; col&#34;节点保存在代码中?为什么XML文档有效呢?

2 个答案:

答案 0 :(得分:2)

disable-output-escaping通常仅在转换的输出直接写入序列化程序时才有效。尽管XSLT规范根据数据模型的扩展描述了它,因此在文本节点中的每个字符都有一个额外的位,表示“禁止转义此字符”,但大多数实现不太可能允许您存储实例此模型作为内存中的树,只有当树从变换器流式传输到串行器时,才会存在额外的位。

(在Saxon的实现中,它不是每个字符使用一个额外的位,而是在从变换器传递到串行器的数据流中插入x00字符以开启或关闭转义;这依赖于x00是合法的这一事实Java中的字符,但不是XML格式。

答案 1 :(得分:1)

好的,我想我已经弄清楚它是如何运作的。除非它们位于CDATA节点中,否则必须转义任何XML保留符号。接下来,什么是disable-output-escaping =&#34; yes&#34;属性将取决于节点类型。如果它是文本节点,它将撤消转义,以便&#34;&amp; lt;&#34;转换为&#34;&lt;&#34;。如果它是CDATA节点,它将禁用转义,CDATA将按原样输出。在任何一种情况下,文本节点中包含的所有标记都会在保留CDATA时被剥离(并根据disable-output-escaping进行转义)。因此,DOMSource或Transformer(不确定谁将DOM呈现给XML)将在转换之前实际转义DOM文本节点(并且CDATA保持不变)。因此,对于文本节点, disable-output-escaping 应该读取 undo-xml-escaping ,这解决了我的困惑。

无论如何,感谢迈克尔的解释!