为什么XPath.evaluate返回NULL? [英] Why XPath.evaluate is returning NULL?

查看:45
本文介绍了为什么XPath.evaluate返回NULL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用以下代码修改xml文件时,出现此错误:

When I use below code to modify an xml file I receive this error :

Exception in thread "main" java.lang.NullPointerException
    at ModifyXMLFile.updateFile(ModifyXMLFile.java:44)
    at ModifyXMLFile.main(ModifyXMLFile.java:56)

该错误发生在以下行:node.setTextContent(newValue);

The error occurs at line : node.setTextContent(newValue);

我不正确使用xpath吗?

Am I not using xpath correctly ?

这是我尝试更新的代码和xml文件

Here is the code and the xml file I'm attempting to update

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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 javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.io.FileUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class ModifyXMLFile {

    public void updateFile(String newValue){

        XPathFactory xPathfactory = XPathFactory.newInstance();
        XPath xpath = xPathfactory.newXPath();

        try {

            File f = new File("C:\\pom.xml");
            InputStream in = new FileInputStream(f);  
            InputSource source = new InputSource(in);

            Node node = (Node)xpath.evaluate("/project/parent/version/text()", source, XPathConstants.NODE);
            node.setTextContent(newValue);

        } catch (XPathExpressionException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }       

    }

    public static void main(String argv[]) {

        new ModifyXMLFile().updateFile("TEST");

    }

}

xml文件:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>testgroup</groupId>
        <artifactId>testartifact</artifactId>
        <version>update</version>
    </parent>

</project>

推荐答案

xmlns="http://maven.apache.org/POM/4.0.0"

表示XML文件中的非前缀元素名称在此命名空间中.在XPath 1.0中,没有前缀的节点名称始终引用 no 命名空间中的节点,因此/project/parent/version 正确不匹配任何内容.

means that the un-prefixed element names in the XML file are in this namespace. In XPath 1.0 unprefixed node names always refer to nodes in no namespace, so /project/parent/version correctly matches nothing.

要匹配XPath中的命名空间节点,您需要将前缀绑定到命名空间URI,然后在表达式中使用该前缀.对于 javax.xml.xpath ,这意味着创建一个 NamespaceContext .不幸的是,标准Java库中没有该接口的默认实现,但是Spring框架提供了

To match namespaced nodes in XPath you need to bind a prefix to the namespace URI and then use that prefix in the expression. For javax.xml.xpath this means creating a NamespaceContext. Unfortunately there are no default implementations of this interface in the standard Java library, but the Spring framework provides a SimpleNamespaceContext that you can use

XPath xpath = xPathfactory.newXPath();
SimpleNamespaceContext nsCtx = new SimpleNamespaceContext();
xpath.setNamespaceContext(nsCtx);
nsCtx.bindNamespaceUri("pom", "http://maven.apache.org/POM/4.0.0");

// ...
Node node = (Node)xpath.evaluate("/pom:project/pom:parent/pom:version/text()", source, XPathConstants.NODE);

也就是说,您仍然需要做更多的工作才能实际修改文件,因为您当前正在加载文件并修改DOM,但随后不将修改后的DOM保存在任何地方.

That said, you'll still need to do a bit more work to actually modify the file, as you're currently loading it and modifying the DOM but then not saving the modified DOM anywhere.

另一种方法可能是使用XSLT:

An alternative approach might be to use XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
                xmlns:pom="http://maven.apache.org/POM/4.0.0">
  <xsl:param name="newVersion" />

  <!-- identity template - copy input to output unchanged except when
       overridden -->
  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <!-- override for the version value -->
  <xsl:template match="pom:version/text()">
    <xsl:value-of select="$newVersion" />
  </xsl:template>
</xsl:stylesheet>

然后,您可以使用 Transformer API调用具有适当参数的样式表

Then you can use the Transformer API to call this stylesheet with an appropriate parameter

StreamSource xslt = new StreamSource(new File("transform.xsl"));
Transformer transformer = TransformerFactory.newInstance().newTransformer(xslt);
transformer.setParameter("newVersion", newValue);
StreamSource input = new StreamSource(new File("C:\\pom.xml"));
StreamResult output = new StreamResult(new File("C:\\updated-pom.xml"));
transformer.transform(input, output);

这篇关于为什么XPath.evaluate返回NULL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆