Я новичок в этом вопросе, но я прочитал много решений по этой теме. К сожалению, все они были в очень простом случае, что я не могу перенаправить свои проблемы. Мой 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>
как раз для того, чтобы лучше объяснить мою ситуацию)
Вот код выполнения разделения с 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();
}
}
}
Я решил это, но мне это совсем не нравится, потому что мне нужно создать временную копию всего 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();
}
Что вы думаете об этой проблеме? если у вас есть предложение улучшить мой код, это будет оценено
Насколько велики вы ожидаете, что ваши документы будут? У вас есть контроль над xml, как вы можете изменить его структуру? он не выглядит семантически правильным (документ внутри заголовка?)
И, разделив файл, вы все еще ожидаете сохранить предыдущую структуру xml? <document1>, <document2>,
не звучит правильно. или какова цель вашего разбиения файла
это нормально, это просто дополнительная информация, которая поможет людям дать вам лучшее решение.