これで、カスタム名前空間を持つ XML ドキュメントができました。(XML は、私たちが制御していないソフトウェアによって生成されます。これは、名前空間を認識しないDOM パーサーによって解析されます。標準の Java7SE/Xerces のものですが、効果的な制御の範囲外でもあります。) 入力データは次のようになります。
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<MainTag xmlns="http://BlahBlahBlah" xmlns:CustomAttr="http://BlitherBlither">
.... 18 blarzillion lines of XML ....
<Thing CustomAttr:gibberish="borkborkbork" ... />
.... another 27 blarzillion lines ....
</MainTag>
取得したドキュメントは使用可能で、xpath クエリ可能で、トラバース可能などです。
このドキュメントをテキスト形式に変換してデータ シンクに書き出すには、100 の SO「how do I change my XML Document into a Java string?」で説明されている標準の Transformer アプローチを使用します。質問:
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter stringwriter = new StringWriter();
transformer.transform (new DOMSource(theXMLDocument), new StreamResult(stringwriter));
return stringwriter.toString();
そしてそれは完全に機能します。
しかし今、そのドキュメントから個々の任意のノードを文字列に変換したいと思います。コンストラクターは、Node ポインターを受け入れるのDOMSource
と同じように Node ポインターを受け入れますDocument
(実際、Document は Node の単なるサブクラスであるため、私が知る限り、同じ API です)。したがって、上記のスニペットの「theXMLDocument」の代わりに個々のノードを渡すとうまく機能します... Thing
.
その時点でtransform()
、例外をスローします。
java.lang.RuntimeException: Namespace for prefix 'CustomAttr' has not been declared.
at com.sun.org.apache.xml.internal.serializer.SerializerBase.getNamespaceURI(Unknown Source)
at com.sun.org.apache.xml.internal.serializer.SerializerBase.addAttribute(Unknown Source)
at com.sun.org.apache.xml.internal.serializer.ToUnknownStream.addAttribute(Unknown Source)
......
それは理にかなっている。(「com.sun.org.apache」は読むのが奇妙ですが、何でもあります。カスタム属性の名前空間がルート ノードで宣言されているため、これは理にかなっていますが、トランスフォーマーは子ノードで開始され、次のことができます。ツリーの「上」にある宣言は表示されません。だから私は問題、または少なくとも症状を理解していると思いますが、それを解決する方法はわかりません。
これが String から Document への変換である場合、
DocumentBuilderFactory
インスタンスを使用して を呼び出すことができます.setNamespaceAware(false)
が、これは逆方向です。で使用可能なプロパティはどれも
transformer.setOutputProperty()
、namespaceURI ルックアップに影響を与えません。これは理にかなっています。そのような対応
setInputProperty
または類似の機能はありません。入力パーサーは名前空間を認識していませんでした。これが、「アップストリーム」コードがドキュメントを作成して私たちに渡す方法でした。その特定のステータスフラグを変換コードに渡す方法がわかりません。これは私が本当にやりたいことだと思います。
ルートMainTag
xmlns:CustomAttr="http://BlitherBlither"
が持っていたのと同じように、Thing ノードに属性を (どういうわけか) 追加できると思います。しかし、その時点で、たとえそれが同じことを「意味」していたとしても、出力は読み込まれたものと同一の XML ではなくなり、テキスト文字列は最終的に将来比較されることになります。例外がスローされるまで、それが必要かどうかはわかりません。その後、追加して再試行できます... ick. さらに言えば、ノードを変更すると元のドキュメントが変更されるため、これは実際には読み取り専用の操作である必要があります。
アドバイス?Transformer に伝える方法はありますか? 「ほら、出力が単独で正当な XML であるかどうかについて、頭のぼんやりした頭を強調しないでください。単独で解析されることはありません (しかし、あなたはそれを知りません)」 、テキストを生成するだけで、そのコンテキストについて心配させてください」?