web-dev-qa-db-ja.com

文字列XMLフラグメントをドキュメントに変換Node in Java

In Javaでは、XMLドキュメントに挿入するためにXMLのフラグメントを表すStringをどのように変換できますか?

例えば.

String newNode =  "<node>value</node>"; // Convert this to XML

次に、このノードをorg.w3c.dom.Documentに特定のノードの子として挿入しますか?

71
James Wardle
Element node =  DocumentBuilderFactory
    .newInstance()
    .newDocumentBuilder()
    .parse(new ByteArrayInputStream("<node>value</node>".getBytes()))
    .getDocumentElement();
60
izb

ドキュメントのimport(またはadopt)XMLフラグメントを追加する方法:

  /**
   * @param docBuilder
   *          the parser
   * @param parent
   *          node to add fragment to
   * @param fragment
   *          a well formed XML fragment
   */
  public static void appendXmlFragment(
      DocumentBuilder docBuilder, Node parent,
      String fragment) throws IOException, SAXException {
    Document doc = parent.getOwnerDocument();
    Node fragmentNode = docBuilder.parse(
        new InputSource(new StringReader(fragment)))
        .getDocumentElement();
    fragmentNode = doc.importNode(fragmentNode, true);
    parent.appendChild(fragmentNode);
  }
32
McDowell

それが価値があるものについては、 dom4j ライブラリを使用して思いついた解決策があります。 (動作することを確認しました。)

XMLフラグメントをorg.dom4j.Documentに読み取ります(注:以下で使用されるすべてのXMLクラスはorg.dom4jからのものです。付録を参照)。

  String newNode = "<node>value</node>"; // Convert this to XML
  SAXReader reader = new SAXReader();
  Document newNodeDocument = reader.read(new StringReader(newNode));

次に、新しいノードが挿入されるドキュメントと、そこから親要素(取得予定)を取得します。 (ここでorg.w3c.dom.Documentをorg.dom4j.Documentに変換する必要があります。)テストのために、次のようなものを作成しました。

    Document originalDoc = 
      new SAXReader().read(new StringReader("<root><given></given></root>"));
    Element givenNode = originalDoc.getRootElement().element("given");

新しい子要素の追加は非常に簡単です。

    givenNode.add(newNodeDocument.getRootElement());

できたoriginalDocを出力すると、次のようになります。

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

<root>
    <given>
        <node>value</node>
    </given>
</root>

付録:あなたの質問はorg.w3c.dom.Documentについて話しているので、ここでそれとorg.dom4j.Documentの間で変換する方法を示します。

// dom4j -> w3c
DOMWriter writer = new DOMWriter();
org.w3c.dom.Document w3cDoc = writer.write(dom4jDoc);

// w3c -> dom4j
DOMReader reader = new DOMReader();
Document dom4jDoc = reader.read(w3cDoc);

(両方の種類のDocumentsを定期的に必要とする場合、これらを適切なユーティリティメソッド、おそらくXMLUtilsまたはそのようなクラスに配置するのが理にかなっているかもしれません。)

サードパーティのライブラリがなくても、これを行うためのより良い方法があるかもしれません。しかし、これまでに提示したソリューションのうち、私の見解では、dom4j <-> w3c変換を行う必要がある場合でも、これが最も簡単な方法です。

Update(2011):dom4j依存関係をコードに追加する前に、 not積極的に保守されているプロジェクトであり、他にもいくつかの問題があります 。改良されたバージョン2.0は長年にわたって機能していましたが、利用できるのはアルファ版のみです。代わりに、XOMなどの代替手段を検討することをお勧めします。上記リンクの質問で詳細をお読みください。

14
Jonik
/**
*
* Convert a string to a Document Object
*
* @param xml The xml to convert
* @return A document Object
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
*/
public static Document string2Document(String xml) throws IOException, SAXException, ParserConfigurationException {

    if (xml == null)
    return null;

    return inputStream2Document(new ByteArrayInputStream(xml.getBytes()));

}


/**
* Convert an inputStream to a Document Object
* @param inputStream The inputstream to convert
* @return a Document Object
* @throws IOException
* @throws SAXException
* @throws ParserConfigurationException
*/
public static Document inputStream2Document(InputStream inputStream) throws IOException, SAXException, ParserConfigurationException {
    DocumentBuilderFactory newInstance = DocumentBuilderFactory.newInstance();
    newInstance.setNamespaceAware(true);
    Document parse = newInstance.newDocumentBuilder().parse(inputStream);
    return parse;
}
6

[〜#〜] xom [〜#〜]ライブラリ を使用したさらに別のソリューションです。 私のdom4jの答え 。 (これは私の dom4jの優れた代替品を見つけるための探求 の一部です。XOMは1つのオプションとして提案されました。)

最初にXMLフラグメントを_nu.xom.Document_に読み取ります。

_String newNode = "<node>value</node>"; // Convert this to XML
Document newNodeDocument = new Builder().build(newNode, "");
_

次に、ドキュメントを取得し、その下にフラグメントが追加されるNodeを取得します。テストのために、文字列からドキュメントを作成します。

_Document originalDoc = new Builder().build("<root><given></given></root>", "");
Element givenNode = originalDoc.getRootElement().getFirstChildElement("given");
_

子ノードの追加は簡単で、dom4jと同様です(ただし、XOMでは、既にnewNodeDocumentに属している元のルート要素を追加できません)。

_givenNode.appendChild(newNodeDocument.getRootElement().copy());
_

ドキュメントを出力すると、正しい結果のXMLが生成されます(XOMを使用すると非常に簡単です。originalDoc.toXML()によって返された文字列を出力するだけです)。

_<?xml version="1.0"?>
<root><given><node>value</node></given></root>
_

(XMLを(インデントと改行を使用して)きれいにフォーマットしたい場合は、 Serializer を使用してください。これを指摘してくれたPeterŠtibranýに感謝します。)

したがって、明らかにこれはdom4jソリューションとそれほど違いはありません。 :)ただし、APIのドキュメントが充実しているため、また各ことを実行するための標準的な方法が1つあるという設計哲学のため、XOMを使用する方が少し良いかもしれません。

付録:繰り返しますが、ここでは_org.w3c.dom.Document_と_nu.xom.Document_の間で変換する方法を示します。 XOMのDOMConverterクラスでヘルパーメソッドを使用します。

_// w3c -> xom
Document xomDoc = DOMConverter.convert(w3cDoc);

// xom -> w3c
org.w3c.dom.Document w3cDoc = DOMConverter.convert(xomDoc, domImplementation);  
// You can get a DOMImplementation instance e.g. from DOMImplementationRegistry
_
6
Jonik

Dom4jを使用している場合は、次のことができます。

ドキュメントドキュメント= DocumentHelper.parseText(text);

(dom4jはここにあります: https://github.com/dom4j/dom4j

4
ronz

...また、純粋にXOMを使用している場合は、次のようになります。

    String xml = "<fakeRoot>" + xml + "</fakeRoot>";
    Document doc = new Builder( false ).build( xml, null );
    Nodes children = doc.getRootElement().removeChildren();
    for( int ix = 0; ix < children.size(); ix++ ) {
        otherDocumentElement.appendChild( children.get( ix ) );
    }

XOMは内部でfakeRootを使用してほぼ同じことを行うため、正確ではないにしても安全でなければなりません。

1
atamar

jcabi-xml を1つのライナーで試してください:

Node node = new XMLDocument("<node>value</node>").node();
1
yegor256