0

私は理解できないように見えるこの奇妙な問題を抱えています。これまで、私の変換メソッドはほとんど問題なく機能しているように見えましたが、現在構築しているツールがいくつかの大きな頭痛の種になっています。

ここに私の方法があります:

これはエラーなく動作し、適切な XML を生成します

    public static void transform(String filename, String filePath, String stylesheetPath, String outputTo, boolean prettyPrint, boolean excludeDeclaration) throws TransformerException, IOException {
        if (!new File(outputTo).exists()) new File(outputTo).mkdir();

        TransformerFactory factory = TransformerFactory.newInstance();
        Source xsl = new StreamSource(new File(stylesheetPath));
        Templates template = factory.newTemplates(xsl);
        Transformer transformer = template.newTransformer();
        if (!prettyPrint) {
            transformer.setOutputProperty(OutputKeys.INDENT, "no");
        } else {
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
        }
        if (excludeDeclaration) transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

        Source xml = new StreamSource(new File(filePath + filename));
        OutputStream outputStream = new FileOutputStream(outputTo + filename);
        transformer.transform(xml, new StreamResult(outputStream));
        outputStream.close();
    }

同じ XSLT を使用して、以下は Text ノードのみを含む (要素、属性などを含まない) XML (または XML からの何か) を生成します。

    public static Document transformInMemory(Document xmlDoc, String stylesheetPath) throws TransformerException, ParserConfigurationException, SAXException, IOException {
        TransformerFactory factory = TransformerFactory.newInstance();
        Source xsl = new StreamSource(new File(stylesheetPath));
        Templates template = factory.newTemplates(xsl);
        Transformer transformer = template.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0");

        DOMSource source = new DOMSource(xmlDoc);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        transformer.transform(source, new StreamResult(baos));

        System.out.println(baos.toString());

        // load into DocumentBuilder
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        InputSource is = new InputSource(new ByteArrayInputStream(baos.toByteArray()));
        return builder.parse(is);
    }

私が行ってきたすべての検索から、2番目の方法で何か間違ったことをしているようには見えませんが、奇妙な結果が得られていることは確かです.

サンプル結果(残念ながら実際のデータを掲載することができないので、テキストを別のデータに置き換えただけです)

    <?xml version="1.0" encoding="UTF-8"?>








                     Some Text Here









                                                        A.



                                                   Some other text here









                                                        B.



                                                   Some more text here









                                                        C.



                                                   And more text here









                                                        D.



                                                   Even more text here















                     A

                1

私が見ているものを正確に見ることができるように、意図的に結果をフォーマットしたままにしました。上記の結果は、 によって生成されるものですSystem.out.println(baos.toString());。コンソール (Eclipse) でテキストを強調表示すると、インデントはすべて表示されますが、すべての要素などが表示されません。

それで、私の質問: 何が起こっている可能性があるか誰か教えてもらえますか? 最初のものは問題なく動作するのに、2番目のものは上記の結果になるのはなぜですか?

編集:

私の方法で遊んだ後、うまくいくと思われる回避策を見つけました。を使用する代わりにDOMSource、xmlDoc を に変換しましたInputStreamが、これは少しハックなようです。なぜDOMSourceこの問題を引き起こしているのかについての考えはありますか?

    public static Document transformInMemory(Document xmlDoc, String stylesheetPath) throws TransformerException, ParserConfigurationException, SAXException, IOException {
        TransformerFactory factory = TransformerFactory.newInstance();
        Source xsl = new StreamSource(new File(stylesheetPath));
        Templates template = factory.newTemplates(xsl);
        Transformer transformer = template.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "no");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "0");

        // convert the xmlDoc to an inputstream
        ByteArrayOutputStream xmlOutStream = new ByteArrayOutputStream();
        Source domSource = new DOMSource(xmlDoc);
        Result result = new StreamResult(xmlOutStream);
        TransformerFactory.newInstance().newTransformer().transform(domSource, result);
        InputStream in = new ByteArrayInputStream(xmlOutStream.toByteArray());

        //DOMSource source = new DOMSource(xmlDoc);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Source source = new StreamSource(in);
        transformer.transform(source, new StreamResult(baos));

        System.out.println("baos -> " + baos.toString());

        // load into DocumentBuilder
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        InputSource is = new InputSource(new ByteArrayInputStream(baos.toByteArray()));
        return builder.parse(is);
    }
4

1 に答える 1

0

デフォルトでは、DocumentBuilder は名前空間を認識しません。NamespaceAware(true) を設定する必要があります。名前空間を認識しないと、スタイルシートのテンプレート ルールが一致しないため、デフォルトのテンプレート ルールが有効になり、これらは単純にテキスト ノードを出力します。

XSLT に入力を提供するためだけに DOM を作成することは、非常に悪い考えであることに注意してください。XSLT プロセッサのネイティブ ツリー表現を使用すると、ほぼ確実にうまく機能します。

于 2013-04-09T07:57:58.827 に答える