Xalan with Java 6是否会跳过评论?

时间:2014-04-10 21:59:10

标签: java xml xslt xalan

在我看来,JDK 6(和7)附带的Xalan版本不会在输入文件中处理注释,如<xsl:template match="comment()" ...>...

所指定的那样

给出以下输入文件dangling.xml

<?xml version="1.0" ?>
<dangling xmlns:dt="urn:uuid:e2973380-8daf-11e3-a5d8-0002a5d5c51b">
   <!--  This is a comment. -->
   <foobar x="y">A bar where I drink foo beer,
           after debugging XSLT in hell all day.</foobar>
</dangling>

和样式表identity_sans_dt.xsl

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:dt="urn:uuid:e2973380-8daf-11e3-a5d8-0002a5d5c51b">


<xsl:output method="xml"
            encoding="UTF-8"
            indent="yes" 
            omit-xml-declaration="yes"
            />

   <xsl:template match="/ | attribute::* | comment()">
     <xsl:copy>
       <xsl:apply-templates select="@*|node()"/>
     </xsl:copy>
   </xsl:template>
   <xsl:template match="*">
      <xsl:element name="{name()}">
         <xsl:apply-templates select="@*|node()"/>
      </xsl:element>
   </xsl:template>
</xsl:stylesheet>

我使用libxml的xsltproc

获得以下输出
<dangling>
   <!--  This is a comment. -->
   <foobar x="y">A bar where I drink foo beer,
           after debugging XSLT in hell all day.</foobar>
</dangling>

然而,当我通过使用SAX TransformerHandler应用相同样式表的Java程序运行相同的东西时,我明白了。

<dangling>

   <foobar x="y">A bar where I drink foo beer,
           after debugging XSLT in hell all day.</foobar>
</dangling>

我做错了什么导致技术规范委婉地称之为“不可预测的结果?”或者是否有一个Xalan错误导致Java版本中的注释被遗漏?

虽然与评论()处理问题没有直接关系,但这是本练习的背景。 dangling.xml是一些先前处理的结果,它删除了dt命名空间中的所有元素及其子元素。出于某种原因,dt命名空间声明被遗忘了。另外,xml声明导致了一些问题。 (这是因为一些下游代码将它作为一个字符串进行操作,只是把它放到另一个XML文本字符串的中间。不要打扰告诉我这有多可怕;我知道。不要打扰告诉那些负责的人所说的代码;我已经。)所以我花了大量的时间试图摆脱这两个恼人的文物,但保留其他一切。

不,dangling.xml不是REAL文件,只是调试的代理。 :-)

因此,如果有一种更好的方法可以回避整个问题,我也有兴趣知道这一点。

提前谢谢。

3 个答案:

答案 0 :(得分:2)

可能是您运行不正确。在SAX中,XMLReader将大多数解析事件通知给已注册的ContentHandler,但不通知注释,这些注释将发送到已注册的LexicalHandler。 JAXP TransformerHandler实现了ContentHandler和LexicalHandler接口,但只有在将XMLReader作为ContentHandler和LexicalHandler注册时才会通知注释。

答案 1 :(得分:1)

我会为遇到这个烦人问题的其他人提供答案。

但首先,我再次感谢Michael Kay指出了最终解决方案的方向。

问题在于,需要在原始XMLReader上设置词法处理程序,该XMLReader首先处理输入。我错误地将问题解释为必须有一个词法处理程序来为了编写最终结果而选择注释。所以我误解了给出的建议。

经过更多的研究后,我发现了我的后续问题的答案,这是&#34;如何在XMLReader上设置词法分析器?&#34;在我看来,这是非常隐蔽的。 SAXParser和XMLReader对象上都有一个setProperty方法,而不是像SAXResult那样简单的setLexicalHandler方法。

 void XMLReader.setProperty(String name, Object value);
 void SAXParser.setProperty(String name, Object value);

&#34;标准&#34;属性名称是http://sax.sourceforge.net/apidoc/org/xml/sax/package-summary.html#package_description指定的URL。其他实现可以添加它们自己的特殊属性,只要它们使用不与标准冲突的URL。这似乎是一种很好的扩展机制,但我不明白为什么他们将它用作API的标准部分的对象;或者相反,为什么他们没有以同样的方式指定所有内容(包括ContentHander)。 (换句话说,一直这样做。)

所以,代替什么,在我一点也不谦虚的意见中应该是一个简单的setLexicalHandler方法,必须使用字符串""http://xml.org/sax/properties/lexical-handler"来指示一个人正在设置词法处理程序,并提供处理程序作为第二个(非类型安全的对象)参数。

所以这是&#34;前端的相关部分&#34;我的计划:

        saxReader = saxParserFactory.newSAXParser().getXMLReader();
        saxReader.setContentHandler(transformsHandler);
        saxReader.setProperty("http://xml.org/sax/properties/lexical-handler", transforms[0]);

如果你没有包含setProperty调用,你的变换器将永远不会在输入中看到注释,因此,就像我的情况一样,XSLT是否处理它们并不重要。那是迈克尔原创的,浓缩的解释。

答案 2 :(得分:0)

最后,我检查过,Sun / Oracle JRE附带的Apache Xalan和Xerces版本已经过时多年,并且有许多已知的错误和限制。除非Oracle在Java 7或Java 8中对此进行了更正 - 即使它们已经更正 - 我强烈建议您直接从Apache下载当前副本并使用它们。

(IBM JRE - 除了作为IBM产品的一部分之外不可用 - 更密切地跟踪Apache,部分原因是IBM团队是Xalan和Xerces的原始捐赠者并且一直参与支持它们。最近的IBM JRE用IBM的下一代XSLT处理器XL-TXE取代了Xalan.IBM WebSphere发布了XL-TXE的高级版本作为其XML Feature Pack的一部分;该版本增加了对XQuery 1.0,XSLT 2.0和XPath 2.0的支持。 )