尝试更新XML中的值时出现javax.xml.xpath.XPathExpressionException

时间:2014-01-30 10:28:06

标签: java xml xpath

我有一个像这样的xml的应用程序:

<root>
<info>
.....
</info>
 <type>
   <object_type>..</object_type>
    <prop>
      <data>
        .... . .. 
    </prop>
    <param>
     ....
    </param>
     <param>
     ....
    </param>
    <param>
     ....
    </param>

所有这些数据都是从XML解析的,现在用户应该可以编辑数据了。 所以我已经实现了一种更新params的方法:

但由于错误编写了Xpath语句,它给了我一个例外:

javax.xml.xpath.XPathExpressionException
    at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.compile(Unknown Source)
    at xmleditor.service.XMLEditorService.updateParameters(XMLEditorService.java:96)
    at xmleditor.gui.XmlEditorMain$5$1.tableChanged(XmlEditorMain.java:364)
    at javax.swing.table.AbstractTableModel.fireTableChanged(Unknown Source)
    at javax.swing.table.AbstractTableModel.fireTableCellUpdated(Unknown Source)
    at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source)
    at javax.swing.JTable.setValueAt(Unknown Source)
    at javax.swing.JTable.editingStopped(Unknown Source)
    at javax.swing.AbstractCellEditor.fireEditingStopped(Unknown Source)
    at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(Unknown Source)
    at javax.swing.DefaultCellEditor.stopCellEditing(Unknown Source)
    at javax.swing.JTable$GenericEditor.stopCellEditing(Unknown Source)
    at javax.swing.DefaultCellEditor$EditorDelegate.actionPerformed(Unknown Source)
    at javax.swing.JTextField.fireActionPerformed(Unknown Source)
    at javax.swing.JTextField.postActionEvent(Unknown Source)
    at javax.swing.JTextField$NotifyAction.actionPerformed(Unknown Source)
    at javax.swing.SwingUtilities.notifyAction(Unknown Source)
    at javax.swing.JComponent.processKeyBinding(Unknown Source)
    at javax.swing.JComponent.processKeyBindings(Unknown Source)
    at javax.swing.JComponent.processKeyEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)


 Caused by: javax.xml.transform.TransformerException: Ett platssteg förväntades efter token  '/' eller '//'.
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.error(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.RelativeLocationPath(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.LocationPath(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.PathExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.UnionExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.UnaryExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.MultiplicativeExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.AdditiveExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.RelationalExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.EqualityExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.AndExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.OrExpr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.Expr(Unknown Source)
    at com.sun.org.apache.xpath.internal.compiler.XPathParser.initXPath(Unknown Source)
    at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source)
    at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source)
    ... 41 more

所以我尝试做的是从用户编辑的表中获取rowCount并将其存储在int x中。然后我将columnName存储在String columnName中。我试图在我的xpath表达式中使用这些变量来根据用户选择的ObjectType找到完美的位置。并更新并将其保存在xml文件中。但不知何故,似乎我的xpath表达式是错误的,或者变换器无法以某种方式读取它。因为我也得到了这个:

Caused by: javax.xml.transform.TransformerException

这是我的java代码:

// Update the parameters
    public void updateParameters(String columnName, Object data, int x,
            Type type) throws ParserConfigurationException, SAXException,
            IOException, XPathExpressionException {

        File file = new File("xmlFiles/CoreDatamodel.xml");
        System.out.println("Incoming String value : " + data);
        System.out.println("Index value : " + x);

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory
                .newInstance();

        DocumentBuilder builder = builderFactory.newDocumentBuilder();

        Document xmlDocument = builder.parse(file);

        XPath xPath = XPathFactory.newInstance().newXPath();

        Node node = (Node) xPath.compile(
                "//OBJECT_TYPE[text() = '" + type.getObjectType()
                        + "']/following-sibling::param/[position()='" + x
                        + "']/'" + columnName + "'").evaluate(xmlDocument,
                XPathConstants.NODESET);

        // Set new NodeValue
        node.setNodeValue(data.toString());

        // Save the new updates
        try {
            save(file, xmlDocument);
        } catch (Exception e) {

            e.printStackTrace();
        }

    }

// Method for saving the new updated data.
    public void save(File file, Document doc) throws Exception {

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer();
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        // Holds the old document
        DOMSource source = new DOMSource(doc);
        transformer.transform(source, result);
        String s = writer.toString();
        System.out.println(s);

        FileWriter fileWriter = new FileWriter(file);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

        bufferedWriter.write(s);
        bufferedWriter.flush();
        bufferedWriter.close();
    }

如何解决这个问题?

更新:

此代码解决了问题,但节点为null,因此表达式正在运行。

Node node = (Node) xPath.compile(
                "//OBJECT_TYPE[text() = '" + type.getObjectType()
                        + "']/following-sibling::param[position()= '" + x
                        + "']/" + columnName + "").evaluate(xmlDocument,
                XPathConstants.NODE);

1 个答案:

答案 0 :(得分:1)

到目前为止,我发现了两个问题:

param*

XPath中的name test与glob的工作方式不同。一般来说,您要么完全匹配名称,要么使用*匹配该轴的主要节点类型的任何节点(通常是元素)。

因此,param*paramparam0param-something-else等内容不匹配,只是表达无效。

/[

你不能过滤任何谓词。节点集必须首先匹配nodetest,然后通过谓词进行过滤。

这里有两种可能性:

  1. /是多余的,必须删除(如果您尝试使用谓词来过滤/之前的表达式返回的节点集)。

  2. 必须在/之后插入nodetest(如果您尝试过滤该节点集中的子节点或子节点)。