4

穏やかな。

javax.xml.transform.Transformer を使用して、いくつかの xml 文字列をタグ間でインデント/スペースなしにフォーマットしようとしています。タグ間にスペースがなければ、問題なく動作します。ある場合、それは奇妙な動作をします。例を投稿します。次のトピックについてフォローアップしようとしました: http://forums.sun.com/thread.jspa?messageID=2054303#2699961。失敗。

従うべきコード:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
   factory.setIgnoringElementContentWhitespace(true);
   DocumentBuilder builder = factory.newDocumentBuilder();
   DOMImplementation domImpl = builder.getDOMImplementation();
   DOMImplementationLS ls = (DOMImplementationLS) domImpl.getFeature("LS", "3.0");
   LSInput in = ls.createLSInput();
   in.setByteStream(new ByteArrayInputStream(input.getBytes()));
   LSParser parser = ls.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS,
     "http://www.w3.org/2001/XMLSchema");
   Document xmlInput = parser.parse(in);

   StringWriter stringWriter = new StringWriter();
   StreamResult xmlOutput = new StreamResult(stringWriter);
   TransformerFactory f = TransformerFactory.newInstance();
   f.setAttribute("indent-number", 2);

   Transformer transformer = f.newTransformer();
   transformer.setOutputProperty(OutputKeys.INDENT, "yes");
   transformer.setOutputProperty(OutputKeys.METHOD, "xml");
   transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
   transformer.transform(new DOMSource(xmlInput), xmlOutput);

タグ間に途切れがない場合

input : <tag><nested>    hello   </nested></tag>
output : 
<tag>
  <nested>    hello   </nested>
</tag>

もしあるなら :

input : <tag>  <nested>    hello   </nested></tag>
output : 
<tag>  <nested>    hello   </nested>
</tag>

JVM 1.6。

ここで何か明らかな問題がありますか?

4

2 に答える 2

3

これは、トランスフォーマーの実装に問題があるはずです。空白や改行のない String を XML として読み取り、XSLT スタイルシート (これも String) から変換プログラムを作成する小さなテスト クラスを作成しました。スタイルシートは、インデントが発生する必要があることを指定します。これは基本的に、これまでに行ったことを達成する別の方法ですtransformer.setOutputProperty(OutputKeys.INDENT, "yes");

ここにあります:

package transformation;

import java.io.StringReader;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class TransformerTest {

    public static void main(String[] args) throws Exception {

        final String xmlSample = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><tag><nested>hello</nested></tag>";
        final String stylesheet = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:output method=\"xml\" version=\"1.0\" indent=\"yes\"/><xsl:template match=\"node()|@*\"><xsl:copy><xsl:apply-templates select=\"node()|@*\"/></xsl:copy></xsl:template></xsl:stylesheet>";

        final TransformerFactory factory = TransformerFactory.newInstance();

        final Source xslSource = new StreamSource(new StringReader(stylesheet));
        final Transformer transformer = factory.newTransformer(xslSource);

        final Source source = new StreamSource(new StringReader(xmlSample));
        final Result result = new StreamResult(System.out);

        transformer.transform(source, result);

    }

}

興味深いのは、使用するトランスによって結果が異なることです。クラスパスに TransformerFactory 実装を配置しない場合 (JRE ライブラリのデフォルト実装を使用)、結果は次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<tag>
<nested>hello</nested>
</tag>

タグがインデントされていないため不正解です。

次に、最近の Xalan 実装をクラスパス (xalan.jar と serializer.jar、まだ JRE デフォルト パーサー/DOM ビルダーを使用) に追加すると、次のようになります。

<?xml version="1.0" encoding="UTF-8"?><tag>
<nested>hello</nested>
</tag>

まだ正しくありません。最初のタグは XML 宣言と同じ行にあり、かつインデントされていません。

正直なところ、これにはかなりショックを受けました。トランスフォーマーはその一部を無視できないと想定する可能性があるため、タグ間またはテキストノードの周囲の空白がインデントに影響を与えるかどうかは理解できます。しかし、そのように単純な XML が壊れているのを見るのは、明らかに奇妙です。コンソール出力の利用が関係しているのではないかと思い、ファイルにストリーミングしてみました。同じ結果です。

長年のトランスフォーマーの実装がまだそのような動作をしているのはちょっと奇妙です。しかし、スキーマのバリデーターを使用すると、「拡張された」XML 出力から属性が削除されることに気付いたときほど悪くはありませんでした。

したがって、他のプロセッサを見つけて、同じ問題が発生しているかどうかを確認する以外に、これについて行うことはあまりないように思われます. たぶん、サクソンは一撃の価値があります。このバグ レポートも興味深いものです (ただし、これは Java 1.5 用です): http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446

于 2011-03-04T19:40:26.830 に答える
0

トランスフォーマーは空白が気に入らないようですので、最も簡単な解決策は単にそれを削除することです....

    public String prettyPrintXML(String inXML)  {

       String outXML = inXML;

// The transformer doesn't like white space between tags so remove it.          
           String[] bits = inXML.split(">");      
       inXML="";
       boolean first = true;
       for (int n=0;n<bits.length; n++){
           if (first)
            inXML = inXML + bits[n].trim();
           else
             inXML = inXML + ">"+bits[n].trim();

           first = false;
       }
      inXML = inXML + ">";

inXML をトランスフォーマーに渡して、すぐに使用できます。

于 2015-05-06T09:20:45.163 に答える