3

XML ドキュメントのオフライン変換をプログラムする必要があります。元の XML ファイルを次のようにロードすると、DTD ネットワーク ルックアップを停止できました。

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 はローカルで利用できますが、ネットワーク ルックアップを試みるのではなく、トランスフォーマーにローカル ファイルを参照させる方法がわかりません。

私が見る限り、トランスフォーマーは変換を正しく行うためにこれらのドキュメントを必要とします。

参考までに、MusicXML ドキュメントを Partwise から Timewise に変換しています。

おそらくご想像のとおり、XSLT は私の得意分野ではありません (それとはかけ離れています)。

ローカル ファイルを参照するように XSLT ファイルを変更する必要がありますか、それとも別の方法で行うことができますか?


以下のコメントに加えて、xsl ファイルの抜粋を次に示します。外部ファイルを参照する唯一の場所です。

<!--
  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" />

言及された手法はこれにも有効ですか?

DTD ファイルには、次のような多数の MOD ファイルへの参照が含まれています。

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

これらのファイルも順番にインポートされると思います。

4

3 に答える 3

6

わかりました、これが私に役立つ答えです。

第 1 ステップ : 元のドキュメントをロードし、ファクトリ内での検証と dtd のロードをオフにします。

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));

2 番目のステップ: ドキュメントをメモリに保存したので、変換する必要があることを検出した後、-

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);

後でさらに処理を行う必要があり、ファイルへの出力とリロードのオーバーヘッドが必要なかったので、これを行う必要がありました。

少し説明:

秘訣は、すべての検証機能がオフになっている元の DOM オブジェクトを使用することです。これはここで見ることができます:

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

これは、ネットワーク アクセスをオフにしてテストされています。したがって、ネットワーク ルックアップがこれ以上ないことはわかっています。

ただし、DTD、MOD などがローカルで利用できる場合は、提案に従って、EntityResolver の使用が答えです。これは、元のdocbuilderオブジェクトに再び適用されます。

これで、変換されたドキュメントがnewdocに保存され、すぐに使用できるようになりました。

これが他の人に役立つことを願っています。

于 2013-09-26T11:32:28.610 に答える
0

Java でこれを行う通常の方法は、LSResourceResolver を使用してシステム ID (および/またはパブリック ID) をローカル ファイルに解決することです。これはhttp://docs.oracle.com/javase/7/docs/api/org/w3c/dom/ls/LSResourceResolver.htmlで文書化されています。これを機能させるために、標準の Java XML パーサー機能以外には何も必要ありません。

于 2013-12-20T07:48:19.907 に答える
0

Apache xml-commons-resolverなどのライブラリを使用し、カタログ ファイルを記述して、Web URL を関連ファイルのローカル コピーにマップできます。このカタログをトランスフォーマー メカニズムに接続するには、スタイルシートのソースとして StreamSource の代わりに SAXSource を使用する必要があります。

SAXSource styleSource = new SAXSource(new InputSource("file:/path/to/stylesheet.xsl"));
CatalogResolver resolver = new CatalogResolver();
styleSource.getXMLReader().setEntityResolver(resolver);
TransformerFactory tf = TransformerFactory.newInstance();
tf.setURIResolver(resolver);
Transformer transformer = tf.newTransformer(styleSource);
于 2013-09-23T22:26:27.977 に答える