web-dev-qa-db-ja.com

XMLファイルから余分な空行を削除する方法は?

要するに; XMLファイルに多くの空の行が生成されていますが、ファイルを傾ける方法としてそれらを削除する方法を探しています。どうやってやるの ?

詳細な説明については、私は現在このXMLファイルを持っています:

<recent>
  <paths>
    <path>path1</path>
    <path>path2</path>
    <path>path3</path>
    <path>path4</path>
  </paths>
</recent>

そして、私はこれをJavaコードを使用してすべてのタグを削除し、代わりに新しいタグを追加します:

public void savePaths( String recentFilePath ) {
    ArrayList<String> newPaths = getNewRecentPaths();
    Document recentDomObject = getXMLFile( recentFilePath );  // Get the <recent> element.
    NodeList pathNodes = recentDomObject.getElementsByTagName( "path" );   // Get all <path> nodes.

    //1. Remove all old path nodes :
        for ( int i = pathNodes.getLength() - 1; i >= 0; i-- ) { 
            Element pathNode = (Element)pathNodes.item( i );
            pathNode.getParentNode().removeChild( pathNode );
        }

    //2. Save all new paths :
        Element pathsElement = (Element)recentDomObject.getElementsByTagName( "paths" ).item( 0 );   // Get the first <paths> node.

        for( String newPath: newPaths ) {
            Element newPathElement = recentDomObject.createElement( "path" );
            newPathElement.setTextContent( newPath );
            pathsElement.appendChild( newPathElement );
        }

    //3. Save the XML changes :
        saveXMLFile( recentFilePath, recentDomObject ); 
}

このメソッドを何度も実行した後、次のように、「パス」タグの後と最初の「パス」タグの前に多くの空の行がある、正しい結果のXMLファイルを取得します。

<recent>
  <paths>





    <path>path5</path>
    <path>path6</path>
    <path>path7</path>
  </paths>
</recent>

誰でもそれを修正する方法を知っていますか?

-------------------------------------------編集:追加getXMLFile(...)、saveXMLFile(...)コード。

public Document getXMLFile( String filePath ) { 
    File xmlFile = new File( filePath );

    try {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document domObject = db.parse( xmlFile );
        domObject.getDocumentElement().normalize();

        return domObject;
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

public void saveXMLFile( String filePath, Document domObject ) {
    File xmlOutputFile = null;
    FileOutputStream fos = null;

    try {
        xmlOutputFile = new File( filePath );
        fos = new FileOutputStream( xmlOutputFile );
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
        transformer.setOutputProperty( "{http://xml.Apache.org/xslt}indent-amount", "2" );
        DOMSource xmlSource = new DOMSource( domObject );
        StreamResult xmlResult = new StreamResult( fos );
        transformer.transform( xmlSource, xmlResult );  // Save the XML file.
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (TransformerConfigurationException e) {
        e.printStackTrace();
    } catch (TransformerException e) {
        e.printStackTrace();
    } finally {
        if (fos != null)
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}
17
Brad

古い「パス」ノードをすべて削除した後、このコードを使用してこれを修正できました:

while( pathsElement.hasChildNodes() )
    pathsElement.removeChild( pathsElement.getFirstChild() );

これにより、XMLファイルで生成されたすべての空のスペースが削除されます。

上記の役立​​つリンクでコメントしてくれた MadProgrammer に特に感謝します。

4
Brad

まず、これが発生する理由の説明— XMLファイルをDOMオブジェクトにロードするために使用されるコードが含まれていないため、少しずれている可能性があります。

ファイルからXMLドキュメントを読み取るとき、DOM仕様に従って、タグ間の空白は実際には有効なDOMノードを構成します。したがって、XMLパーサーは、このような一連の空白文字をDOMノード(TEXTタイプ)として扱います。

それを取り除くために、私が考えることができる3つのアプローチがあります:

  • XMLをスキーマに関連付けてから、DocumentBuilderFactorysetValidating(true)setIgnoringElementContentWhitespace(true)とともに使用します。

    (注:setIgnoringElementContentWhitespaceは、パーサーが検証モードの場合にのみ機能するため、setValidating(true)を使用する必要があります)

  • すべてのノードを処理するXSLを記述し、空白のみのTEXTノードを除外します。
  • Javaコードを使用してこれを行う:XPathを使用してすべての空白のみのTEXTノードを検索し、それらを反復処理してそれぞれをその親から削除します(getParentNode().removeChild()を使用) )のようなものです(docはDOMドキュメントオブジェクトです):

    XPath xp = XPathFactory.newInstance().newXPath();
    NodeList nl = (NodeList) xp.evaluate("//text()[normalize-space(.)='']", doc, XPathConstants.NODESET);
    
    for (int i=0; i < nl.getLength(); ++i) {
        Node node = nl.item(i);
        node.getParentNode().removeChild(node);
    }
    
24
Isaac

Xmlをすばやく「クリーンアップ」するだけでよい場合は、 this のようなものを見ることができます。それからあなたは次のような方法を持つことができます:

public static String cleanUp(String xml) {
    final StringReader reader = new StringReader(xml.trim());
    final StringWriter writer = new StringWriter();
    try {
        XmlUtil.prettyFormat(reader, writer);
        return writer.toString();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return xml.trim();
}

また、必要に応じて、アンチェチェックの違いを比較するには、次のようにします。 XMLUnit

1
mdm

以下のコードを使用しています:

System.out.println("Start remove textnode");
        i=0;
        while (parentNode.getChildNodes().item(i)!=null) {
            System.out.println(parentNode.getChildNodes().item(i).getNodeName());
            if (parentNode.getChildNodes().item(i).getNodeName().equalsIgnoreCase("#text")) {
                parentNode.removeChild(parentNode.getChildNodes().item(i));
                System.out.println("text node removed");
            }
            i=i+1;

        }
1
Jlearner

私も同じ問題に直面し、長い間何も知りませんでしたが、今、このブラッドの質問と彼自身の質問に対する彼自身の答えの後、どこに問題があるのか​​がわかりました。

アイザックが言ったように、ブラッドの答えは本当に完璧ではないので、私は自分の答えを追加する必要があります。

私は子ノードが何であるかを知らずに盲目的に子ノードを削除する大ファンではないでしょう

したがって、より良い「解決策」(回避策である可能性が高いため引用)は次のとおりです。

_pathsElement.setTextContent("");
_

これにより、不要な空白行が完全に削除されます。すべての子ノードを削除するよりも間違いなく優れています。ブラッド、これもあなたのために働くはずです。

しかし、これは原因ではなく結果であり、原因ではなくこの影響を取り除く方法を得ました。

原因:removeChild()を呼び出すと、この子が削除されますが、削除された子のインデントが残り、改行も行われます。そして、このindent_and_like_breakはテキストコンテンツとして扱われます。

したがって、原因を取り除くには、子とそのインデントを削除する方法を理解する必要があります。ようこそ これに関する質問

1
Dmitry Frank

いくつかの注意点:1)XMLを操作しているとき(要素を削除するか、新しい要素を追加するとき)、XSLT(DOMではなく)を使用することを強くお勧めします2)XMLドキュメントをXSLTで変換するとき(saveメソッドと同じように) 、OutputKeys.INDENTを "no"に設定します。3)xmlの単純な後処理(空白、コメントなどを削除する)には、単純なSAX2フィルターを使用できます。

0
rmuller

DOM処理API(DOM4Jなど)を使用している場合、空行を取り除く非常に簡単な方法があります。

  • 保持したいテキストを変数に入れます(つまりtext
  • node.setText("")を使用してノードテキストを ""に設定します
  • ノードテキストをtextに設定するnode.setText(text)を使用

そして出来上がり!空の行はもうありません。他の回答は、xml出力の余分な空行が実際にテキストタイプの余分なノードである方法を非常によく示しています。

この手法は、テキスト設定関数の名前がAPIの名前に合うように変更されている限り、任意のDOM解析システムで使用できます。したがって、それを少し抽象的に表現する方法です。

お役に立てれば:)

0
GMasucci
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace(true);
0
Tai Le