Java XML 解析 - xi:include の出力のマージで、投稿者は XInclude を使用しようとしましたが、include
要素で間違った名前空間を使用していました。XMLFilter が名前空間の修正を処理する XInclude 認識パーサーの前に配置された XMLFilter は、この問題を解決できると考えました (修正された名前空間を持つ中間ファイルを最初に作成する別の処理ステップを使用せずに、ファイルをそれぞれ手動で編集する必要はありません)。 .
そこで、SAX が提供する をXMLFilter
拡張して、次のように記述しました。XMLFilterImpl
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLFilterImpl;
public class XIncludeNsFixup extends XMLFilterImpl {
static String correctURI = "http://www.w3.org/2001/XInclude";
static String oldURI = "http://www.w3.org/2003/XInclude";
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (uri.equals(oldURI)) {
super.startElement(correctURI, localName, qName, atts);
}
else {
super.startElement(uri, localName, qName, atts);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (uri.equals(oldURI)) {
super.endElement(correctURI, localName, qName);
}
else {
super.endElement(uri, localName, qName);
}
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
if (uri.equals(oldURI)) {
super.startPrefixMapping(prefix, correctURI);
}
else {
super.startPrefixMapping(prefix, uri);
}
}
}
次に、XInclude 対応の SAXParser をそれぞれ作成して、XMLReader
そのフィルターにチェーンし、サンプル ドキュメントをSAXSource
そのフィルターからデフォルトにロードして、次のTransformer
ようにビルドしDOMResult
ます。
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setXIncludeAware(true);
XMLReader inputReader = spf.newSAXParser().getXMLReader();
XMLFilter fixNs = new XIncludeNsFixup();
fixNs.setParent(inputReader);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer builder = tf.newTransformer();
DOMResult fixedInput = new DOMResult();
builder.transform(new SAXSource(fixNs, new InputSource("file3.xml")), fixedInput);
Document doc = (Document) fixedInput.getNode();
Transformer serializer = tf.newTransformer();
serializer.transform(new DOMSource(doc), new StreamResult(System.out));
file3.xml
私が使用したサンプル ドキュメントxi:xinclude
には、適切な XInclude 名前空間に 1 つの要素と、サポートされていない古い名前空間に1 つの要素があります。
<?xml version="1.0" encoding="UTF-8"?>
<contexts>
<context name="a">
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/>
<foo>Original text 1.</foo>
</context>
<context name="b">
<xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/>
<foo>Original text 2.</foo>
</context>
</contexts>
私の期待は、フィルターが最初に名前空間を修正し、次に XMLReader が両方の要素に対して XInclude を実行することです。ただし、Java 1.8 でコードを実行すると、出力は次のようになります。
<?xml version="1.0" encoding="UTF-8" standalone="no"?><contexts>
<context name="a">
<text xml:base="reuse.xml">I am XIncluded text.</text>
<foo>Original text 1.</foo>
</context>
<context name="b">
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/>
<foo>Original text 2.</foo>
</context>
</contexts>
そのため、フィルターは 2 番目の要素の名前空間を修正しましたが、XMLReader は最初の要素include
に XInclude の包含のみを適用しました。include
どこで間違ったのですか?フィルターと XInclude 対応の XMLReader をチェーンして名前空間を修正し、名前空間が修正された要素に対して XInclude インクルードを実行するにはどうすればよいですか?
完全を期すために、次のreuse.xml
とおりです。
<?xml version="1.0" encoding="UTF-8"?>
<text>I am XIncluded text.</text>
簡単なテストを可能にする Java プログラムの完全なコード:
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
import org.xml.sax.XMLReader;
public class XIncludeTest1 {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException, TransformerException {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setXIncludeAware(true);
XMLReader inputReader = spf.newSAXParser().getXMLReader();
XMLFilter fixNs = new XIncludeNsFixup();
fixNs.setParent(inputReader);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer builder = tf.newTransformer();
DOMResult fixedInput = new DOMResult();
builder.transform(new SAXSource(fixNs, new InputSource("file3.xml")), fixedInput);
Document doc = (Document) fixedInput.getNode();
Transformer serializer = tf.newTransformer();
serializer.transform(new DOMSource(doc), new StreamResult(System.out));
}
}
また、Apache の最新の Xerces Java をクラスパスに配置して、問題が解決するかどうかを確認しようとしましたが、出力は同じままです。