如何在 Java 中使用 xpath 在 xml 中查找节点值或属性并将其替换为另一个值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16578814/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 23:21:17  来源:igfitidea点击:

How do I use xpath in Java to find a node value or attribute in an xml and replace it with another value?

javaxmlxpath

提问by Sahil Gupta

Here is my Code so far:

到目前为止,这是我的代码:

// locate the node(s)
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xpath.evaluate("//root[text()='input[1]']", doc, XPathConstants.NODESET);

// make the change
for (int idx = 0; idx < nodes.getLength(); idx++) {
    nodes.item(idx).setTextContent(input[3]);
}

// save the result
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(new DOMSource(doc), new StreamResult(new File(outputFile)));


Input[1] is what I am looking for in the XML, and input [3] is what it is being replaced with.

Input[1] 是我在 XML 中寻找的内容,而 input [3] 是它被替换的内容。

Here is the XML:

这是 XML:

<root> 
    <accounts> 
        <account name="Bill Gates">
            <position>CEO</position> 
            <phoneNumber>123-485-1854</phoneNumber>
            <notes>Runs the company</notes> 
        </account> 
        <account name="Service Account"/> 
        <account name="Burt Mackland"> 
            <position>CFO</position> 
            <phoneNumber>345-415-4813</phoneNumber> 
            <notes>Great CFO</notes> </account> 
        <account name="Joe Smith"> 
            <position>Accountant</position>
            <reportsTo>Burt Mackland</reportsTo>
            <phoneNumber>135-118-7815</phoneNumber> 
            <notes>Must have ID checked at all Gates</notes>
        </account> 
    </accounts> 
    <departments> 
        <deparment name="Finance"> 
            <employeeCount>2</employeeCount> 
        </deparment> 
        <department name="Human Resources"> 
            <employeeCount>0</employeeCount> 
        </department> 
        <department name="Executive"> 
            <employeeCount>2</employeeCount>
        </department> 
    </departments> 
</root>

The user may not know what is in the XML. So i cannot hardcode the Xpath in the code. Please any would be greatly appreciated!

用户可能不知道 XML 中的内容。所以我不能在代码中硬编码 Xpath。请任何人将不胜感激!

回答by acdcjunior

As you want to search for text in any element (not only <root>), change the XPath expression from

如果您想在任何元素(不仅是<root>)中搜索文本,请将 XPath 表达式从

//root[text()='TEXT-TO-BE-FOUND']

To

//*[text()='TEXT-TO-BE-FOUND']

To find all attributes with the same value, you must use the following XPath expression:

要查找具有相同值的所有属性,必须使用以下 XPath 表达式:

//*/@*[.='TEXT-TO-BE-FOUND']

Also, as you can't hardcode, make TEXT-TO-BE-FOUNDa variable. (Note: TEXT-TO-BE-FOUNDmust be escaped, it may not contain 'as it will affect the XPath expression.)

此外,由于您无法进行硬编码,因此请创建TEXT-TO-BE-FOUND一个变量。(注意:TEXT-TO-BE-FOUND必须转义,它可能不包含,'因为它会影响 XPath 表达式。)

Working code below. It will replace all elements and all atributes with the input value:

下面的工作代码。它将用输入值替换所有元素和所有属性:

import java.io.File;
import java.util.Scanner;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import org.w3c.dom.*;

public class XmlChange {

    public static void main(String argv[]) throws Exception {
        Scanner keyboard = new Scanner(System.in);
        System.out.print("Type like textToFind,textToReplace: "); // type, for example CEO,Chief Executive Officer
        String next = keyboard.nextLine();

        String[] input = next.split(",");

        String textToFind = input[0].replace("'", "\'"); //"CEO";
        String textToReplace = input[1].replace("'", "\'"); // "Chief Executive Officer";
        String filepath = "root.xml";
        String fileToBeSaved = "root2.xml";

        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
        Document doc = docBuilder.parse(filepath);

        XPath xpath = XPathFactory.newInstance().newXPath();
        // change ELEMENTS


        String xPathExpression = "//*[text()='" + textToFind + "']";
        NodeList nodes = (NodeList) xpath.evaluate(xPathExpression, doc, XPathConstants.NODESET);

        for (int idx = 0; idx < nodes.getLength(); idx++) {
            nodes.item(idx).setTextContent(textToReplace);
        }

        // change ATTRIBUTES
        String xPathExpressionAttr = "//*/@*[.='" + textToFind + "']";
        NodeList nodesAttr = (NodeList) xpath.evaluate(xPathExpressionAttr, doc, XPathConstants.NODESET);

        for(int i=0; i<nodesAttr.getLength(); i++) {
            nodesAttr.item(i).setTextContent(textToReplace);
        }
        System.out.println("Everything replaced.");

        // save xml file back
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(new File(fileToBeSaved));
        transformer.transform(source, result);
    }
}