JAVA根据属性值删除XML节点

时间:2019-05-05 10:35:56

标签: java xml

我有以下XML,如果状态匹配为DEACTIVATED,我将尝试从其中删除整个节点。

下面是 input.xml

<devicesInfo>
    <deviceID>DEVICE1</deviceID>
    <secondaryDevice>false</secondaryDevice>
    <status>ACTIVE</status>
</devicesInfo>
<devicesInfo>
    <deviceID>DEVICE2</deviceID>
    <secondaryDevice>false</secondaryDevice>
    <status>DEACTIVATED</status>
</devicesInfo>
<devicesInfo>
    <deviceID>DEVICE3</deviceID>
    <secondaryDevice>false</secondaryDevice>
    <status>ACTIVE</status>
</devicesInfo>
<devicesInfo>
    <deviceID>DEVICE4</deviceID>
    <secondaryDevice>false</secondaryDevice>
    <status>ACTIVE</status>
</devicesInfo>

,所需的输出为:

<devicesInfo>
    <deviceID>DEVICE1</deviceID>
    <secondaryDevice>false</secondaryDevice>
    <status>ACTIVE</status>
</devicesInfo>
<devicesInfo>
    <deviceID>DEVICE3</deviceID>
    <secondaryDevice>false</secondaryDevice>
    <status>ACTIVE</status>
</devicesInfo>
<devicesInfo>
    <deviceID>DEVICE4</deviceID>
    <secondaryDevice>false</secondaryDevice>
    <status>ACTIVE</status>
</devicesInfo>

我已经能够提取与状态已停用相匹配的deviceID,但是在删除整个节点方面却很困难

void removeDeactivatedDevices() throws SAXException, IOException, ParserConfigurationException {
        String device;
        try {
            File inputFile = new File(input.xml);
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(inputFile);

            doc.getDocumentElement().normalize();
            NodeList nList = doc.getElementsByTagName("devicesInfo");

            for (int i = 0; i < nList.getLength(); i++) {
                Node nNode = nList.item(i);

                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) nNode;

                    if (eElement.getElementsByTagName("status").item(0).getTextContent().contentEquals("DEACTIVATED")) {
                        device = eElement.getElementsByTagName("deviceID").item(0).getTextContent();

                        // print out the devices that match this status
                        System.out.println(device);

                                  // HELP Need to delete parent node of that device...
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

因此,当我运行它时,我得到:

DEVICE1
DEVICE3
DEVICE4

我想要的是返回的完整XML,而不包含DEACTIVATED Status项目。

2 个答案:

答案 0 :(得分:1)

好吧,假设您正在使用org.w3c.dom.*库来解析XML文档,这应该很容易。只需使用Document.removeChild(node)

这里有个例子:

import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class MainClass {


    public static void main(String[] args) throws Exception {
        File f = new File("input.xml");
        Document XML_DOC = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f);
        NodeList devices = XML_DOC.getElementsByTagName("devicesInfo");
        printDocument(XML_DOC);


        for (int i = 0; i < devices.getLength(); i++) {
            Node device = devices.item(i);
            if(isDeviceDeactivated(device))
                //remove from .item(0) because we have to remove them from the <devices> node
                XML_DOC.getChildNodes().item(0).removeChild(device);

        }

        System.out.println("");System.out.println("");
        System.out.println("------------------------------------");
        printDocument(XML_DOC);
    }

    public static void printDocument(Document doc) throws IOException, TransformerException {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");


        transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(System.out, "UTF-8")));
    }

    public static boolean isDeviceDeactivated(Node node) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            Element e = (Element) node;
            if (e.getElementsByTagName("status").item(0).getTextContent().contentEquals("DEACTIVATED"))
                return true;
        }
        return false;
    }

}

用于测试此内容的XML文档:(我必须将设备信息列表包装在另一个节点上)

<?xml version="1.0" encoding="UTF-8"?>
<devices>
    <devicesInfo>
        <deviceID>DEVICE1</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
    <devicesInfo>
        <deviceID>DEVICE2</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>DEACTIVATED</status>
    </devicesInfo>
    <devicesInfo>
        <deviceID>DEVICE3</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
    <devicesInfo>
        <deviceID>DEVICE4</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
</devices>

该代码仅输出:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<devices>
    <devicesInfo>
        <deviceID>DEVICE1</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
    <devicesInfo>
        <deviceID>DEVICE2</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>DEACTIVATED</status>
    </devicesInfo>
    <devicesInfo>
        <deviceID>DEVICE3</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
    <devicesInfo>
        <deviceID>DEVICE4</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
</devices>


------------------------------------
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<devices>
    <devicesInfo>
        <deviceID>DEVICE1</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>

    <devicesInfo>
        <deviceID>DEVICE3</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
    <devicesInfo>
        <deviceID>DEVICE4</deviceID>
        <secondaryDevice>false</secondaryDevice>
        <status>ACTIVE</status>
    </devicesInfo>
</devices>

答案 1 :(得分:0)

我尝试了以下方法,也使用xPath解决了该问题

void removeDevicesWithDeactivatedStatus() throws SAXException, IOException, ParserConfigurationException, XPathExpressionException,
            TransformerException {

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true); // never forget this!
        Document document = dbf.newDocumentBuilder().parse(new File("input.xml"));

        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();
        XPathExpression expression = xpath.compile("//devices/devicesinf[status/text()='DEACTIVATED']");

        // 1) Get book titles written after 2001
        Object result = expression.evaluate(document, XPathConstants.NODESET);

        NodeList nodes = (NodeList) result;

        int numberOfDeactivatedDevices = 0;
        for (int i = 0; i < nodes.getLength(); i++) {
            numberOfDeactivatedDevices = +i;
            // System.out.println(nodes.item(i).getNodeValue() + " [" + i+"]");
            Node b13Node = (Node) expression.evaluate(document, XPathConstants.NODE);
            b13Node.getParentNode().removeChild(b13Node);

        }

        System.out.println("Deactivated devices removed: " + numberOfDeactivatedDevices);

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        t.transform(new DOMSource(document), new StreamResult(new File("output.xml")));
        //t.transform(new DOMSource(document), new StreamResult(System.out));
}