【问题标题】:How to do a XSL transform in Java using a not namespace aware parser?如何使用不支持命名空间的解析器在 Java 中进行 XSL 转换?
【发布时间】:2015-06-08 11:18:09
【问题描述】:

我将tagsoup 用作(SAX)XMLREader,并将命名空间功能设置为false。此解析器用于将Transformer 作为 SAX 源提供。完整代码:

    final TransformerFactory factory = TransformerFactory.newInstance();
    final Transformer t = factory.newTransformer(new StreamSource(
        getClass().getResourceAsStream("/identity.xsl")));

    final XMLReader p = new Parser(); // the tagsoup parser
    p.setFeature("http://xml.org/sax/features/namespaces", false);

    // getHtml() returns HTML as InputStream
    final Source source = new SAXSource(p, new InputSource(getHtml())); 

    t.transform(source, new StreamResult(System.out));

结果如下:

< xmlns:html="http://www.w3.org/1999/xhtml">
<>
<>
<>
<>
< height="17" valign="top">

问题是标签名称为空。 XMLReader(tagsoup 解析器)确实在 SAX 方法 ContentHandler#startElementContentHandler#endElement 中报告了空的 namespaceURI 和空的本地名称。对于不支持命名空间的解析器,这是允许的(参见Javadoc)。

如果我添加一个XMLFilter,它将qName 的值复制到localName,一切都会正常。但是,这不是我想要的,我希望这可以“开箱即用”。我究竟做错了什么?任何意见将不胜感激!

【问题讨论】:

  • 为什么需要将 XSLT 与不支持命名空间的 XmlReader 一起使用?众所周知,XSLT/XPath 需要命名空间格式正确的输入。
  • 如果启用了命名空间,我需要像 h:html/h:body/h:table/h:tbody/h:tr 这样的 xpath 表达式,而不是 html/body/table/tbody/tr(简短的回答:因为我很懒和/或我对 xslt 的了解很烂)。
  • 请注意,根据 home.ccil.org/~cowan/tagsoup/#program 的 TagSoup 有一个选项 --nons 来抑制命名空间(命名空间被抑制。)。我猜你也可以使用它的 API 来启用它,在这种情况下,当你解析 HTML 时,报告的元素应该不在命名空间中(XSLT/XPath 可以处理)。
  • @MartinHonnen --nons 命令行选项与我的示例中使用的 p.setFeature("http://xml.org/sax/features/namespaces", false); 相同。抑制命名空间实际上是我正在寻找的地方!
  • 如果命令行选项只是设置了解析器功能,那么我同意 Ian 的回答。

标签: java xslt sax tag-soup


【解决方案1】:

我希望这可以“开箱即用”。我做错了什么?

您做错的事情是采用一种技术 (XSLT),该技术被定义为对命名空间格式良好的 XML 进行操作,并试图将其应用于不打算使用的数据。如果您想使用 XSLT,那么您必须启用命名空间,在样式表中为 http://www.w3.org/1999/xhtml 命名空间声明一个前缀,并在 XPath 表达式中一致地使用该前缀。

如果您的转换器理解 XSLT 2.0(例如 Saxon 9),那么您可以将 xpath-default-namespace="http://www.w3.org/1999/xhtml" 放在 xsl:stylesheet 元素上,而不是在 XPath 表达式中声明前缀并为元素名称添加前缀,以使其将无前缀元素名称视为对该命名空间的引用。但在 XSLT 1.0(默认的内置 Java Transformer 实现)中,您唯一的选择是使用前缀。

【讨论】:

  • 非常明确的答案!对我来说,缺少的链接是:如果您想使用 XSLT,那么您必须启用名称空间在输入文档上。我确实知道 XSLT 2 功能,但是对于这个项目,只有 XSLT 1 可用,我真的很讨厌一遍又一遍地使用前缀,所以在输入文档上禁用命名空间是很聪明的 :)
  • 作为补充:我在 Javadoc 中找不到关于此前提条件的提及!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-28
相关资源
最近更新 更多