TransformerFactory - 避免通过网络查找来验证 DTD [英] TransformerFactory - avoiding network lookups to verify DTDs

查看:38
本文介绍了TransformerFactory - 避免通过网络查找来验证 DTD的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为 XML 文档的离线转换编程.使用以下内容加载原始 XML 文件时,我已经能够停止 DTD 网络查找:

I am needing to program for offline transformation of XML documents. I have been able to stop DTD network lookups when loading the original XML file with the following :

DocumentBuilderFactory factory;

factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(true);
factory.setFeature("http://xml.org/sax/features/namespaces", false);
factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
// open up the xml document
docbuilder = factory.newDocumentBuilder();
doc = docbuilder.parse(new FileInputStream(m_strFilePath));

但是,我无法将其应用于 TransformerFactory 对象.DTD 在本地可用,但我不知道如何指示转换器查看本地文件,而不是尝试进行网络查找.

However, I am unable to apply this to the TransformerFactory object. The DTDs are available locally, but I do not know how to direct the transformer to look at the local files as opposed to trying to do a network lookup.

据我所知,转换器需要这些文件才能正确进行转换.

From what I can see, the transformer needs these documents to correctly do the transformation.

有关信息,我正在将 MusicXML 文档从 Partwise 转换为 Timewise.

For information, I am transforming MusicXML documents from Partwise to Timewise.

您可能已经猜到了,XSLT 不是我的强项(远非如此).

As you have probably guessed, XSLT is not my strong point (far from it).

我是否需要修改 XSLT 文件以引用本地文件,或者是否可以采用不同的方式?

Do I need to modify the XSLT files to reference local files, or can this be done differently ?

除了下面的评论,这里是 xsl 文件的摘录.这是我看到的唯一引用外部文件的地方:

Further to the comments below, here is an excerpt of the xsl file. It is the only place that I see which refers to an external file :

<!--
  XML output, with a DOCTYPE refering the timewise DTD.
  Here we use the full Internet URL. 
-->
<xsl:output method="xml" indent="yes" encoding="UTF-8"
    omit-xml-declaration="no" standalone="no"
    doctype-system="http://www.musicxml.org/dtds/timewise.dtd"
    doctype-public="-//Recordare//DTD MusicXML 2.0 Timewise//EN" />

上述技术是否也适用于此?

Is the mentioned technique valid for this also ?

DTD 文件包含对许多 MOD 文件的引用,如下所示:

The DTD file contains references to a number of MOD files like this :

<!ENTITY % layout PUBLIC
    "-//Recordare//ELEMENTS MusicXML 2.0 Layout//EN"
    "layout.mod">

我认为这些文件也将依次导入.

I presume that these files will also be imported in turn also.

推荐答案

好的,这是对我有用的答案.

Ok, here is the answer which works for me.

第一步:加载原始文档,关闭工厂内的验证和dtd加载.

1st step : load the original document, turning off validation and dtd loading within the factory.

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// stop the network loading of DTD files
factory.setValidating(false);
factory.setNamespaceAware(true);
factory.setFeature("http://xml.org/sax/features/namespaces", false);
factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
// open up the xml document
DocumentBuilder docbuilder = factory.newDocumentBuilder();
Document doc = docbuilder.parse(new FileInputStream(m_strFilePath));

第二步:现在我已经在内存中获得了文档......并且在检测到我需要转换它之后 -

2nd step : Now that I have got the document in memory ... and after having detected that I need to transform it -

TransformerFactory transformfactory = TransformerFactory.newInstance();
Templates xsl = transformfactory.newTemplates(new StreamSource(new FileInputStream((String)m_XslFile)));
Transformer transformer = xsl.newTransformer();
Document newdoc = docbuilder.newDocument();
Result XmlResult = new DOMResult(newdoc);
// now transform
transformer.transform(
        new DOMSource(doc.getDocumentElement()),
        XmlResult);

我需要这样做,因为我之后还有进一步的处理,并且不希望输出到文件和重新加载的开销.

I needed to do this as I have further processing going on afterwards and did not want the overhead of outputting to file and reloading.

小解释:

诀窍是使用已关闭所有验证功能的原始 DOM 对象.你可以在这里看到:

The trick is to use the original DOM object which has had all the validation features turned off. You can see this here :

transformer.transform(
        new DOMSource(doc.getDocumentElement()),  // <<-----
        XmlResult);

这已经在网络访问关闭的情况下进行了测试.所以我知道没有更多的网络查找.

This has been tested with network access TURNED OFF. So I know that there are no more network lookups.

但是,如果 DTD、MOD 等在本地可用,那么根据建议,使用 EntityResolver 就是答案.这将再次应用于原始 docbuilder 对象.

However, if the DTDs, MODs, etc are available locally, then, as per the suggestions, the use of an EntityResolver is the answer. This to be applied, again, to the original docbuilder object.

我现在有一个转换后的文档存储在 newdoc 中,可以使用了.

I now have a transformed document stored in newdoc, ready to play with.

我希望这会对其他人有所帮助.

I hope this will help others.

这篇关于TransformerFactory - 避免通过网络查找来验证 DTD的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆