【问题标题】:How do I use xpath in Java to find a node value or attribute in an xml and replace it with another value?如何在 Java 中使用 xpath 在 xml 中查找节点值或属性并将其替换为另一个值?
【发布时间】:2013-05-10 20:05:59
【问题描述】:

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

// 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] 是我在 XML 中寻找的内容,而 input [3] 是它被替换的内容。

这是 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>

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

【问题讨论】:

  • 还有人会碰巧知道如何部分更改节点值和属性值吗?意思是,给定搜索词“Gates”,它可以在两个地方找到,一个是节点值,另一个是属性值。我将如何更改它,以便仅用用户输入替换 Gates 这个词?

标签: java xml xpath


【解决方案1】:

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

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

到

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

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

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

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

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

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);
    }
}

【讨论】:

  • 嗯...这是一个非常好的主意,但由于某种原因,将其作为变量似乎不起作用。我让用户输入要查找的文本和要替换的文本,所以我也不能对它们进行硬编码。
  • // 定位节点 XPath xpath = XPathFactory.newInstance().newXPath(); NodeList 节点 = (NodeList)xpath.evaluate(input[1], doc, XPathConstants.NODESET);
  • 我有,我的用户输入为: System.out.println("To modify a basic file Type:"); System.out.println("find, //*[text()=''], 替换为, .");
  • 要使该代码正常工作,input 必须是 String[],第二项(即索引 1)应该是 xPath 表达式。您从哪里获取此用户输入?
  • 我还需要能够查看属性值并在必要时替换它们...
猜你喜欢
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多