การคัดลอกและเปลี่ยนชื่อองค์ประกอบจากไฟล์ XML หนึ่งไฟล์เป็นไฟล์ XML อื่นใน Java

ฉันสามารถคัดลอกโหนดจากไฟล์ XML หนึ่งไปยังอีกไฟล์หนึ่งได้โดยใช้ "org.w3c.dom.Document.importNode(Node importNode, boolean deep)"
อย่างไรก็ตาม ฉัน ดูเหมือนจะไม่สามารถเปลี่ยนชื่อองค์ประกอบที่ฉันกำลังคัดลอกได้

ฉันมีบางอย่างเช่น:
File1.xml

<SomeCustomNode randomAttribute="aValue" another="10/10/2010">  
    <Information>  
        <Yellow name="banana"/>  
        <Orange name="orange"/>  
        <Red name="strawberry"/>  
    </Information>  
    <Some>  
        <IgnoredNode/>  
    </Some>  
</SomeCustomNode>  

และอะไรทำนองนี้:
FileList.xml

<ListOfNodes date="12/10/2010">  
    <aCopy name="fruit" version="10">  
        <Yellow name="banana"/>  
        <Orange name="orange"/>  
        <Red name="strawberry"/>  
    </aCopy>  
    <aCopy name="vegetables" version="3">  
        <Yellow name="sweetcorn"/>  
        <Orange name="carrot"/>  
        <Red name="tomato"/>  
    </aCopy>  
</ListOfNodes>  

ดังนั้น สิ่งที่ฉันกำลังทำคือนำโหนด (และลูก ๆ ) จาก File1.xml และแทรกลงใน FileList.xml แต่เปลี่ยนชื่อ Element และเพิ่มแอตทริบิวต์สองสามรายการให้กับองค์ประกอบ
ข้อมูล กลายเป็น aCopy name="fruit" version="10"

ขณะนี้ฉันกำลังใช้นิพจน์ XPath เพื่อรับโหนด ข้อมูล เป็น NodeList (ผลลัพธ์เพียง 1 รายการ) จากนั้นนำเข้าสิ่งนั้นลงใน File2 ดังนี้:

Document docFile1 = XMLDocumentStore.getDoc("/path/to/File1.xml");  
Document docFileList = XMLDocumentStore.getDoc("/path/to/FileList.xml");  
NodeList result = XPathAPI.selectNodeList(docFile1.getFirstChild(), ".//Information");  
Node importNode = docFileList.importNode(result.item(0), true);  
// We want to replace aCopy fruit with the updated version found in File1  
NodeList fruitNode = XPathAPI.selectNodeList(docFileList.getFirstChild(), ".//aCopy[@name=\"fruit\"]");  
Node replaceNode = fruitNode.item(0).getParentNode().replaceChild(importNode, fruitNode.item(0)); // probably a better way to do this  
// Now we want to replace the Element name as it is still set to Information  
docFileList.renameNode(replaceNode, null, "aCopy"); // Error: oracle.xml.parser.v2.XMLDOMException: cannot add attribute belonging to another element  

ฉันได้รับข้อผิดพลาดอื่นๆ หากฉันย้ายโค้ดไปรอบๆ เล็กน้อย เช่น: ไม่สามารถลบหรือแทนที่โหนดได้ ไม่ใช่โหนดลูกของโหนดปัจจุบัน ฯลฯ

จะดีกว่านี้ผ่าน XSLT หรือไม่ ทั้งหมดที่ฉันทำคือนำโหนดเฉพาะ (และเป็นโหนดย่อย) และใส่ลงในไฟล์ XML อื่น แต่เปลี่ยนชื่อองค์ประกอบและเพิ่มแอตทริบิวต์ 2 รายการ (ด้วยค่า) มันจะเป็นโหนดเดียวกันสำหรับแต่ละไฟล์ (File1 ... File###) และจะถูกเปลี่ยนชื่อในลักษณะเดียวกัน ค่าแอตทริบิวต์จะถูกนำมาจากไฟล์ต้นฉบับ (เช่น File1.xml สำหรับตัวอย่างของฉัน) และส่วนย่อย โหนดไม่ได้รับการเปลี่ยนแปลง (สีเหลือง, สีส้ม, สีแดงในตัวอย่างของฉัน)
ไชโย!


person dan2k3k4    schedule 26.10.2010    source แหล่งที่มา
comment
สิ่งนี้จะเหมาะกับ Scala มากกว่ามากซึ่งมีการรองรับ XML ดั้งเดิม XSLT เป็นโลกแห่งความเจ็บปวดที่ยิ่งใหญ่กว่าที่คุณพบอยู่ในปัจจุบัน หากคุณสงสัย โปรดดูที่ scala-lang.org/node/131 - หาก คุณไม่อยากรู้อยากเห็น ฉันขอให้คุณโชคดีในการค้นหาคำตอบ   -  person Synesso    schedule 26.10.2010
comment
ฉันอยากจะแนะนำให้ใช้ XSLT โดยเฉพาะอย่างยิ่งสำหรับการเปลี่ยนแปลงง่ายๆ เช่นนี้ การใช้ DOM ไม่ใช่วิธีแก้ปัญหาที่ดีนักหากคุณต้องจัดการกับไฟล์ XML ขนาดใหญ่   -  person gcores    schedule 26.10.2010
comment
@ Synesso - นอกหัวข้อเล็กน้อย แต่ฉันถูกล่อลวงโดย Scala แม้ว่าฉันจะต้องเรียนรู้และทำให้ทีมของฉันยอมรับ ฯลฯ แม้ว่าฉันจะสามารถใช้ Scala ภายในโปรเจ็กต์ Java ได้ใช่ไหม เพิ่ม Scala ให้กับพาธคลาส/บิลด์ จากนั้นตั้งค่าคลาส Scala เพื่อโต้ตอบกับคลาส Java   -  person dan2k3k4    schedule 26.10.2010
comment
@ gcores - ฉันคิดว่า fileList จะไม่เกิน 700 โหนด aCopy และแต่ละโหนด aCopy จะมีโหนดย่อยระหว่าง 2 ถึง 8 โหนด (สีส้ม/เหลือง/แดงจากตัวอย่าง) มันใหญ่เกินไปสำหรับ DOM หรือไม่?   -  person dan2k3k4    schedule 26.10.2010


คำตอบ (1)


เหตุใดคุณจึงใช้ Oracle XML Parser

หากคุณใช้ค่าเริ่มต้นที่ได้รับจาก javax.xml คุณจะไม่ได้รับข้อผิดพลาดนี้:

import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.org.apache.xpath.internal.XPathAPI;

public static void main(String[] args) throws Exception {

    Document docFile1 = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("File1.xml"));
    Document docFileList = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File("FileList.xml"));
    NodeList result = XPathAPI.selectNodeList(docFile1.getFirstChild(), ".//Information");
    Node importNode = docFileList.importNode(result.item(0), true);  
    // We want to replace aCopy fruit with the updated version found in File1  
    NodeList fruitNode = XPathAPI.selectNodeList(docFileList.getFirstChild(), ".//aCopy[@name=\"fruit\"]");
    Node replaceNode = fruitNode.item(0).getParentNode().replaceChild(importNode, fruitNode.item(0)); // probably a better way to do this  
    // Now we want to replace the Element name as it is still set to Information  
    docFileList.renameNode(replaceNode, null, "aCopy"); 

    print(docFileList);

}

พิมพ์ออกมา:

<ListOfNodes date="12/10/2010">  
    <Information>  
        <Yellow name="banana"/>  
        <Orange name="orange"/>  
        <Red name="strawberry"/>  
    </Information>  
    <aCopy name="vegetables" version="3">  
        <Yellow name="sweetcorn"/>  
        <Orange name="carrot"/>  
        <Red name="tomato"/>  
    </aCopy>  
</ListOfNodes>
person dogbane    schedule 26.10.2010
comment
อืมคุณพูดถูก ดูเหมือนว่าจะมีปัญหากับการนำเข้าของฉัน จะต้องแก้ไขสิ่งนั้น ฉันได้สร้างเครื่องมือของฉันตามโปรเจ็กต์ที่มีอยู่แล้ว แต่ฉันสามารถสลับการนำเข้าหรือแก้ไขสำหรับคลาสนี้เพียงคลาสเดียวได้ ไชโย! - person dan2k3k4; 26.10.2010