Java: DOM, как переименовать имена узлов из списка имен - PullRequest
0 голосов
/ 12 февраля 2012

Я новичок в DOM, и у меня есть следующее требование.У меня есть следующая упрощенная структура XML:

<?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 должен работать.У меня есть ArrayList, который содержит 3 имени.Но тогда индексы моего ArrayList и моего cs - NodeList не совпадают.У меня есть 3 <C> элементов, но NodeList cs содержит семь узлов вместо 3.

Кто-нибудь знает, как я мог решить эту проблему?Или есть другой, лучший, более элегантный способ добиться этого?

Спасибо за вашу помощь и наилучшие пожелания, Питер

Ответы [ 2 ]

1 голос
/ 13 февраля 2012

Вы можете использовать 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));
1 голос
/ 13 февраля 2012

Похоже, XSLT может быть лучше подходит для этого. Вы можете использовать функцию position() для генерации имен элементов. Посмотрите этот ответ для более подробной информации.

...