【问题标题】:Replace text in XML before XSLT在 XSLT 之前替换 XML 中的文本
【发布时间】:2014-01-08 20:44:39
【问题描述】:

在将 XML 文件中的某些文本提供给 XSL-Transformer 之前,我需要替换它。 它是DOCTYPE 标记中的DTD-URL。它指向一个网络服务器,但我希望它可以离线使用,所以我想将其更改为指向本地文件的 URL。

但是我不能直接编辑原始 XML。我想将文件读入字符串,在文本上使用String.replaceAll() 并将其保存到另一个文件中,然后将其传递给 Transformer。我已经试过了,但是真的很慢;我正在使用的文件大小为 ca. 500kiB。

有没有更好(=更快)的方法来实现这一点?

EDIT:用于转换的代码:

public String getPlaylist(String playlist) {
    Source source = new StreamSource(library);
    StreamSource xsl = new StreamSource(getClass().getResourceAsStream("M3Utransformation.xml"));
    StringWriter w = new StringWriter();
    Result result = new StreamResult(w);
    try {
        Transformer transformer = TransformerFactory.newInstance().newTransformer(xsl);
        transformer.setParameter("playlist", playlist);
        transformer.transform(source, result);
        return w.getBuffer().toString();
    } catch (Throwable t) {
        t.printStackTrace();
        return null;
    }
}

【问题讨论】:

  • 根据 W3C 的说法,有很多过多的 DTD 流量,请参阅w3.org/blog/systeam/2008/02/08/w3c_s_excessive_dtd_traffic 这让我想到了一个问题,你真的需要你的 dtd 吗?我会追查并回答这个问题,但我想我会先要求您提供无法访问 dtd 失败的代码示例
  • 要转换的 XML 文件不是我创建的。这是一个 iTunes 库。我不想弄乱图书馆本身。
  • 大多数 XML 解析器,以及至少一些 XSLT 处理器,都有一个 API,允许您编写和插入可以对部分或全部 URL/URI 提供特殊解释的代码。这可用于识别 DTD 请求并返回从您想要的任何地方获得的输入流——范围从内存中的字符串到本地文件到文件缓存,具体取决于您想要做多少工作。这通常称为“DTD 解析器”或“实体解析器”,具体取决于您用于运行样式表的 API。

标签: java xml xslt file-io


【解决方案1】:

您可以创建一个实体解析器并使用它。

以下示例使用 JAXP DocumentBuilder 和 CatalogResolver

public static void main(String[] args) throws ParserConfigurationException,
        SAXException, IOException, TransformerConfigurationException, TransformerException {

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    db.setEntityResolver(new CatalogResolver());

    File src = new File("src/article.xml");
    Document doc = db.parse(src);

    // Here, we execute the transformation
    // Use a Transformer for output
    File stylesheet = new File("src/aticle.xsl");
    TransformerFactory tFactory = TransformerFactory.newInstance();
    StreamSource stylesource = new StreamSource(stylesheet);
    Transformer transformer = tFactory.newTransformer(stylesource);

    DOMSource source = new DOMSource(document);
    StreamResult result = new StreamResult(System.out);
    transformer.transform(source, result);
}

创建一个目录属性文件,并将其放在您的类路径中 CatalogManager.properties 必须是名称,请参阅CatalogManager API documentation

定义一个目录 XML 文件,将您的属性文件指向它上面。从 http://www.xml.com/pub/a/2004/03/03/catalogs.html你可以找到一个非常简单的目录XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
  <public publicId="-//OYRM/foo" uri="src/bar.dtd"/>
</catalog>

使用上述catalog.xml 和CatalogManager.properties,您最终会将publicId“-//OYRM/foo”的引用解析为uri src/bar.dtd xml-commons 包含解析器:

http://xerces.apache.org/mirrors.cgi#binary

要更完整地处理解析器的主题,请阅读Tom White's article from XML.com

转换器应用程序是从可扩展样式表语言转换的 Java 线索中抄袭的 > Transforming Data with XSLT

【讨论】:

  • 我如何将Document doc 给变压器?
  • 编辑自己搞定:new DOMSource(doc)。非常感谢。
  • 我编辑了上面的内容以完成转换并将数据发送到 System.out ...很高兴你得到它@the_Seppi,但我想我会完成编辑以完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 2018-10-07
  • 2012-02-06
相关资源
最近更新 更多