2012-02-12 169 views
0

我是DOM新手,我有以下要求。 我有以下簡單的XML結構:Java:DOM如何從名稱列表中重命名節點名稱

<?xml version="1.0"?> 
<ExportData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<DataSet> 
    <Tables> 
     <Table> 
      <Rows> 
       <R> 
        <C>101</C> 
        <C>1503</C> 
        <C>2012-02-09 00:00:00</C> 
       </R> 
       <R> 
        <C>101</C> 
        <C>1503</C> 
        <C>2012-02-09 00:00:00</C> 
       </R> 
      </Rows> 
     </Table> 
    </Tables> 
</DataSet> 
</ExportData> 

所有<C>元素(的<R>孩子)我需要根據3個字符串列表進行重命名。 所以輸出應該是這樣的:

<?xml version="1.0"?> 
<ExportData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<DataSet> 
    <Tables> 
     <Table> 
      <Rows> 
       <R> 
        <Name1>101</Name1> 
        <Name2>1503</Name2> 
        <Name3>2012-02-09 00:00:00</Name3> 
       </R> 
       <R> 
        <Name1>101</Name1> 
        <Name2>1503</Name2> 
        <Name3>2012-02-09 00:00:00</Name3> 
       </R> 
      </Rows> 
     </Table> 
    </Tables> 
</DataSet> 

我想DOM會做到這一點的最佳選擇。我想出了以下情況:

import java.io.File; 
import java.io.FileInputStream; 
import java.util.ArrayList; 
import javax.xml.transform.*; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 

import org.w3c.dom.*; 
import renameElementNames.DOMUtils; 

public class ParseNavigate { 

public static void main(String[] args) throws Exception { 
    final DOMImplementation domImpl = DOMUtils.getImplementationFromRegistry(DOMUtils.DOM_FEATURE_Core_30_LS); 
    final Document doc = DOMUtils.parse(domImpl, new FileInputStream("examplefiles/1503_roh_2012-02-09small.xml")); 
    changeTagNames(doc); 
    writeXmlFile(doc,"output.xml"); 
} 


public static void changeTagNames (Document doc){ 
    ArrayList<String> attlist = new ArrayList<String>(); 
    String name1 = "Name1";String name2 = "Name2";String name3 = "Name3"; 
    attlist.add(name1);attlist.add(name2);attlist.add(name3); 

    Node rows = doc.getElementsByTagName("Rows").item(0); 
    NodeList rs = rows.getChildNodes(); 


    for(int i=0;i<rs.getLength();i++){ 
     Node r = rs.item(i); 
     NodeList cs = r.getChildNodes(); 
     System.out.println(rs.getLength()); 
     for(int j=0;j<cs.getLength();j++){ 
      System.out.println(cs.getLength()); 
      Node c = cs.item(j); 
      if(c.getNodeType() == Node.ELEMENT_NODE){ 
       doc.renameNode(c,c.getNamespaceURI(),attlist.get(j)); 
      } 
     } 
    } 
} 

public static void writeXmlFile(Document doc, String filename) { 
    try { 
     // Prepare the DOM document for writing 
     Source source = new DOMSource(doc); 

     // Prepare the output file 
     File file = new File(filename); 
     Result result = new StreamResult(file); 

     // Write the DOM document to the file 
     Transformer xformer = TransformerFactory.newInstance().newTransformer(); 
     xformer.transform(source, result); 
    } catch (TransformerConfigurationException e) { 
    } catch (TransformerException e) { 
    } 
} 
} 

所以changeTagNames方法是應該做的工作。我有一個包含3個名稱的ArrayList。但是,我的ArrayList和我的0123List的索引是不一樣的。我有3 <C>元素,但節點列表cs擁有七個節點,而不是3.

有誰知道我該如何解決這個問題?還是有另一種更好,更優雅的方式來實現這一目標?

謝謝您的幫助和問候, 彼得

回答

1

您可以使用jOOX執行此任務,並將邏輯寫入類似jquery的樣式。例如:

// Create the list of new tag names 
final List<String> names = Arrays.asList("Name1", "Name2", "Name3"); 
final Document doc = ... 

// Find all <R/> elements and iterate over their <C/> children 
$(doc).find("R").children("C").each(new Each() { 
    public void each(Context context) { 

    // Get the appropriate tag name corresponding to the iteration index 
    String newTagName = names.get(context.elementIndex() % names.size()); 

    // Use the DOM API to rename the node 
    doc.renameNode(context.element(), "", newTagName); 
    } 
}); 

// Check results 
System.out.println($(doc)); 

正如您所看到的,這可以通過Java中的幾行完成。另一個選項

final Document doc = ... 

// Iterate over <R/> elements 
for (Match r : $(doc).find("R").each()) { 

    // Iterate over <C/> children and rename nodes 
    Match c = r.children("C"); 
    for (int i = 0; i < c.size(); i++) { 
    doc.renameNode(c.get(i), "", "Name" + (i + 1)); 
    } 
} 

// Check results 
System.out.println($(doc)); 
+0

你好盧卡斯,謝謝。我下載了「jOOX-1.0.0.zip」並添加爲庫。但是「import static org.joox.JOOX。*;」導致錯誤「導入org.joox無法解析」。你能告訴我,我做錯了什麼。 – Peter 2012-02-13 09:53:04

+0

@Peter:你必須把庫放在你的編譯器/運行時類路徑中...看一看[這個問題](http://stackoverflow.com/questions/4590739/setting-the-classpath) – 2012-02-13 09:54:00

+0

謝謝Lukas , 這是工作! – Peter 2012-02-13 11:33:32

1

好像XSLT可能是這更好的配合。您可以使用position()函數來生成元素名稱。請參閱this answer瞭解更多詳情。

+0

Hello hertzsprung,Thank you。是的,我同意你的看法,但要求是我只能使用java。問候,彼得 – Peter 2012-02-13 09:54:03