2017-09-19 8 views
1

ネストされたタグ/配列をすべて単純なキー/値のペアにすることによって、XML文書をフラット化する方法はありますか?たとえば、私は JavaでのXML文書の統合

root.a.0.b=some-value1 
root.a.0.c=some-value2 
root.a.1.b=some-value3 
root.a.1.c=some-value4 
root.p=some-value-p 

TO例

<root> 
<a> 
    <b>some-value1</b> 
    <c>some-value2</c> 
</a> 
<a> 
    <b>some-value3</b> 
    <c>some-value4</c> 
</a> 
<p>some-value-p</p> 

を持っている私は、JavaやScalaでは、いくつかの解決策を探していますか?

+1

あなたはすべてのリーフノードを探し、そしてドットで彼らの親階層を連結することができ、おそらく子供のためのいくつかの余分なロジックが必要になります。 – epoch

答えて

2

ここには外部依存関係のないソリューションがあります。あなたはtry itすることができます!

import org.w3c.dom.Document; 
import org.w3c.dom.Element; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 
import org.xml.sax.SAXException; 

import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 
import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.nio.charset.StandardCharsets; 

public class Main { 

    private static final String xml = 
      "<root>\n" + 
      " <a>\n" + 
      "  <b>some-value1</b>\n" + 
      "  <c>some-value2</c>\n" + 
      " </a>\n" + 
      " <a>\n" + 
      "  <b>some-value3</b>\n" + 
      "  <c>some-value4</c>\n" + 
      " </a>\n" + 
      " <p>some-value-p</p>\n" + 
      "</root>"; 

    public static void main(String[] args) { 
     try { 
      byte[] bytes = xml.getBytes(StandardCharsets.UTF_8); 
      try (InputStream input = new ByteArrayInputStream(bytes)) { 
       Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(input); 
       Element root = document.getDocumentElement(); 
       flattXml("", root); 
      } 
     } catch (IOException | ParserConfigurationException | SAXException e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void flattXml(String currentPath, Node currentNode) { 
     if (currentNode.getNodeType() == Node.TEXT_NODE && 
       !currentNode.getNodeValue().trim().isEmpty()) { 
      System.out.println(currentPath + "=" + currentNode.getNodeValue()); 
     } else { 
      NodeList childNodes = currentNode.getChildNodes(); 
      int length = childNodes.getLength(); 
      String nextPath = currentPath.isEmpty() 
        ? currentNode.getNodeName() 
        : currentPath + "." + currentNode.getNodeName(); 
      for (int i = 0; i < length; i++) { 
       Node item = childNodes.item(i); 
       flattXml(nextPath, item); 
      } 
     } 
    } 

} 

コンソール出力は:

root.a.b=some-value1 
root.a.c=some-value2 
root.a.b=some-value3 
root.a.c=some-value4 
root.p=some-value-p 
+0

ありがとう、これは完全に動作します – user667022

2

あなたはあなたがここ

#converted XML 
#Tue Sep 19 15:15:57 CEST 2017 
a.2.c=some-value4 
a.2.b=some-value3 
p=some-value-p 
a.1.c=some-value2 
a.1.b=some-value1 

を取得する代わりに

root.a.0.b=some-value1 
root.a.0.c=some-value2 
root.a.1.b=some-value3 
root.a.1.c=some-value4 
root.p=some-value-p 

のジャクソン

を使用することができ、テストコードです:

import com.fasterxml.jackson.dataformat.javaprop.JavaPropsMapper; 
import com.fasterxml.jackson.dataformat.xml.XmlMapper; 
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; 
import java.io.IOException; 
import java.io.StringReader; 
import java.util.List; 
import java.util.Properties; 
import org.junit.Test; 

public class TestXMLConversion { 
    public static final String XML = 
"<root>\n" + 
"<a>\n" + 
" <b>some-value1</b>\n" + 
" <c>some-value2</c>\n" + 
"</a>\n" + 
"<a>\n" + 
" <b>some-value3</b>\n" + 
" <c>some-value4</c>\n" + 
"</a>\n" + 
"<p>some-value-p</p>" + 
"</root>"; 

    public static class Root { 
     @JacksonXmlElementWrapper(useWrapping=false) 
     private List<A> a; 
     private String p; 

     public List<A> getA() { 
      return a; 
     } 

     public void setA(List<A> a) { 
      this.a = a; 
     } 

     public String getP() { 
      return p; 
     } 

     public void setP(String p) { 
      this.p = p; 
     } 
    } 

    public static class A { 
     private String b; 
     private String c; 

     public String getB() { 
      return b; 
     } 

     public void setB(String b) { 
      this.b = b; 
     } 

     public String getC() { 
      return c; 
     } 

     public void setC(String c) { 
      this.c = c; 
     } 
    } 

    @Test 
    public void test() throws IOException { 
     XmlMapper xmlMapper = new XmlMapper(); 
     Root parsedData = xmlMapper.readValue(new StringReader(XML), Root.class); 

     JavaPropsMapper propertiesMapper = new JavaPropsMapper(); 
     Properties properties = propertiesMapper.writeValueAsProperties(parsedData); 

     properties.store(System.out, "converted XML"); 
    } 
} 

私が使用した依存関係:

<dependency> 
    <groupId>com.fasterxml.jackson.dataformat</groupId> 
    <artifactId>jackson-dataformat-xml</artifactId> 
    <version>2.9.1</version> 
</dependency> 
<dependency> 
    <groupId>com.fasterxml.jackson.dataformat</groupId> 
    <artifactId>jackson-dataformat-properties</artifactId> 
    <version>2.9.1</version> 
</dependency> 
<dependency> 
    <groupId>junit</groupId> 
    <artifactId>junit</artifactId> 
    <version>4.12</version> 
    <scope>test</scope> 
</dependency> 
0

XMLを解析してから、ノードツリーを再帰的に調べて、親を追跡します。それから、parent + "。" +ノード+ "=" +値。

もしそれを変換するという問題を抱えているのであれば、ジャクソンのようなものを使っても便利なオブジェクトに直接解析する方が簡単かもしれません。次に、XMLの属性のようなものについて説明することができます。