Разделить XML-файл с помощью Java

1

Я новичок в этом вопросе, но я прочитал много решений по этой теме. К сожалению, все они были в очень простом случае, что я не могу перенаправить свои проблемы. Мой XML-документ структурирован как:

<messagge>
  <heading>
    <context>
      <forniture>
        <fornitureHeading>..other tags..</fornitureHeading>
        <document>
          ...other tags...
        </document>
        <document>
         ...
        </document>
        ...
      </forniture>
    </context>
  </heading>
</messagge>

Мне нужно создать один новый XML файл foreach <document> но мне нужно сохранить всю информацию выше (теги - атрибут - и все такое):

document1.xml

<messagge>
  <heading>
    <context>
      <forniture>
        <fornitureHeading>..other tags..</fornitureHeading>
        <document1>
          ...other tags...
        </document1>
      </forniture>
    </context>
  </heading>
</messagge>

document2.xml

<messagge>
  <heading>
    <context>
      <forniture>
        <fornitureHeading>..other tags..</fornitureHeading>
        <document2>
          ...other tags...
        </document2>
      </forniture>
    </context>
  </heading>
</messagge>

так.... Я пробовал этот скрипт qaru.site/questions/1359081/...

File input = new File(pathFile);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = dbf.newDocumentBuilder().parse(input);
XPath xpath = XPathFactory.newInstance().newXPath();

NodeList nodes = (NodeList) xpath.evaluate("//Message/Context/Forniture/Document", doc, XPathConstants.NODESET);

int itemsPerFile = 1;
int fileNumber = 0;
Document currentDoc = dbf.newDocumentBuilder().newDocument();
Node rootNode = currentDoc.createElement("Message");

File currentFile = new File(OUTPUT_FOLDER+fileNumber+".xml");
for (int i=1; i <= nodes.getLength(); i++) {
    Node imported = currentDoc.importNode(nodes.item(i-1), true);
    rootNode.appendChild(imported);

    if (i % itemsPerFile == 0) {
        writeToFile(rootNode, currentFile);

        rootNode = currentDoc.createElement("Messaggio");
        currentFile = new File(OUTPUT_FOLDER+(++fileNumber)+".xml");
    }
}

Проблема с этим скриптом заключается в том, что он записывает в новый файл только <document>, а не также родительский тег. Теперь ясный и равный связанный, но я попробовал некоторое решение для записи также верхних узлов, добавил их в NodeList, а затем попытался добавить к этому каждый узел <document>, но не работал. Любое предложение будет оценено. благодаря

Дополнительная информация:

-I не может изменить структуру XML

-I необходимо поддерживать ту же структуру (<document1><document2> как раз для того, чтобы лучше объяснить мою ситуацию)

  • 0
    у вас есть xsd, которому соответствует этот XML?
  • 0
    Да, но (я не знаю, если это так) сложный xsd, с большим количеством файлов, которые его составляют
Показать ещё 4 комментария
Теги:
xpath

3 ответа

0

Вот код выполнения разделения с vtd-xml и XPath, я использовал XPath для навигации по структуре документа... и элемент Fragment обозначается его смещением и значением...

import com.ximpleware.*;
import java.io.*;
public class simpleSplit {
    public static void main(String[] s) throws VTDException, IOException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("d:\\xml\\message.xml", true)) //namespace awareness disabled
            return;
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn), ap2=new AutoPilot(vn);
        XMLModifier xm = new XMLModifier(vn);
        ap.selectXPath("/messagge/heading/context/forniture/document"); //first xpath
        FastLongBuffer fib= new FastLongBuffer();// grab all the fragments
        int i=0;long l1=0,l2=0,l3=0;
        while((i=ap.evalXPath())!=-1){
            fib.append(vn.getElementFragment());
        }   
        ap2.selectXPath("/messagge/heading/context/forniture"); //second xpath
        i=ap2.evalXPath();
        if(vn.toElement(VTDNav.FIRST_CHILD,"fornitureHeading")){
            l1= vn.getElementFragment();
            vn.toElement(VTDNav.P);
        }
        l2 = vn.getContentFragment();
        for (int j=0;j<fib.size();j++){
            xm.insertAfterHead(vn,l1);
            xm.removeContent((int)(l2),(int)(l2>>32));
            l3= fib.longAt(j);
            xm.insertBeforeTail(vn,l3);
            xm.output("d:\\xml\\outMessage"+(j+1)+".xml");
            xm.reset();
        }
    }
}
0

Я решил это, но мне это совсем не нравится, потому что мне нужно создать временную копию всего XML файла для каждого <document> внутри. Это потому, что я тупо забыл простую, но основную вещь: документ, элемент, узел, класс... являются объектом !! и копия - это мелкая копия.

Решение связано с этой проблемой

public static void separaDichiarazioniXML(String pathINFile, String pathOUTFile) throws Exception{

    DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder domparser = dbfactory.newDocumentBuilder();
    Document doc = domparser.parse(new File(pathINFile));

    Node messaggio = doc.getFirstChild();
    Node contenuto = null;

    boolean intestazione = false;
    for(int i=0; i<messaggio.getChildNodes().getLength();i++){
        if(messaggio.getChildNodes().item(i).getNodeType() == Node.ELEMENT_NODE){
            if(intestazione){
                contenuto = messaggio.getChildNodes().item(i);
                intestazione = false;
                for(int j=0; j<contenuto.getChildNodes().getLength();j++){
                    if(contenuto.getChildNodes().item(j).getNodeType() == Node.ELEMENT_NODE){
                        NodeList doc730 = doc.getElementsByTagName("m730:Documento730");
                        for(int k=0; k<doc730.getLength(); k++){
                    //NEED TO CREATE ANOTHER COPY OF THE DOCUMENT FOR NOT CHANGE DATA IN THE CURRENT MEMORY REFERENCE WHERE I'M WORKING
                    //USING ALL INDEXES FOUND
                            Document docTmp = domparser.parse(new File(pathINFile));
                            Node messaggioTmp = docTmp.getFirstChild();
                            Node contenutoTmp = messaggioTmp.getChildNodes().item(i);
                            Node fornituraTmp = contenutoTmp.getChildNodes().item(j);
                            NodeList doc730Tmp = docTmp.getElementsByTagName("m730:Documento730");
                            for(int t=0; t<doc730.getLength(); t++){
                                if(k!=t){   
                                    fornituraTmp.removeChild(doc730Tmp.item(t));
                                }
                            }
                            writeToFile(messaggioTmp, new File(pathOUTFile+"doc_"+k+".xml"));
                        }
                    }
                }
            }else{
                intestazione = true;
            }
        }
    }      
}

или я не понял поведения DOMparsing в Java, или это проблема, которая не может быть решена при низких вычислительных затратах. Я определенно предпочитаю решение, которое я уже реализовал: unmarshalling и marshalling, доступный мне, благодаря XJC, объектной структуре моего XML-документа. Это предыдущее решение mi

//structure for temporary copy
JAXBContext jcc = JAXBContext.newInstance(Messaggio.class);
Unmarshaller uu = jcc.createUnmarshaller();
Messaggio mIntestazione = (Messaggio) uu.unmarshal(new InputStreamReader(
                    new ByteArrayInputStream(bb),
                    "UTF-8"));
//clean temporary structure documents
mIntestazione.getContenuto().getFornitura().getDocumento().clear();
//structure for elaboration
JAXBContext jc = JAXBContext.newInstance(Messaggio.class);
Unmarshaller u = jc.createUnmarshaller();
Messaggio m = (Messaggio) u.unmarshal(new InputStreamReader(
                    new ByteArrayInputStream(bb),
                    "UTF-8"));

Fornitura f = m.getContenuto().getFornitura();

for (Documento doc : f.getDocumento()) {
    String fileOut = nomeFile.substring(0, nomeFile.lastIndexOf("."))+"_"+doc.getIdentificativo();
    //add the current elaboration doc at temporary structure for print it in a separate file
    mIntestazione.getContenuto().getFornitura().getDocumento().add(doc);
    JAXBContext jout = JAXBContext.newInstance(Messaggio.class);
    Marshaller mx = jout.createMarshaller();
    mx.setProperty(mx.JAXB_FORMATTED_OUTPUT, new Boolean(true));
    mx.marshal(mIntestazione, new File(_PathOut_+fileOut+_XML));
    //clean temporary structure
    mIntestazione.getContenuto().getFornitura().getDocumento().clear();
}

Что вы думаете об этой проблеме? если у вас есть предложение улучшить мой код, это будет оценено

0

Насколько велики вы ожидаете, что ваши документы будут? У вас есть контроль над xml, как вы можете изменить его структуру? он не выглядит семантически правильным (документ внутри заголовка?)

И, разделив файл, вы все еще ожидаете сохранить предыдущую структуру xml? <document1>, <document2>, не звучит правильно. или какова цель вашего разбиения файла

это нормально, это просто дополнительная информация, которая поможет людям дать вам лучшее решение.

  • 0
    Андреа, я не понимаю отрицательный голос? эти вопросы нужны, чтобы помочь вам ... как сейчас, опция jaxb хороша, если файлы не такие большие
  • 0
    я не понизил .... я не понял ваш вопрос
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню