gpt4 book ai didi

java - XPath、XML 命名空间和 Java

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:00:22 24 4
gpt4 key购买 nike

过去一天我一直在尝试从以下文档中提取一个 XML 节点,但无法掌握 XML 命名空间的细微差别以使其正常工作。

XML 文件太大,无法全部发布,所以这里是我关心的部分:

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<XFDL xmlns="http://www.PureEdge.com/XFDL/6.5" xmlns:custom="http://www.PureEdge.com/XFDL/Custom" xmlns:designer="http://www.PureEdge.com/Designer/6.1" xmlns:pecs="http://www.PureEdge.com/PECustomerService" xmlns:xfdl="http://www.PureEdge.com/XFDL/6.5">
<globalpage sid="global">
<global sid="global">
<xmlmodel xmlns:xforms="http://www.w3.org/2003/xforms">
<instances>
<xforms:instance id="metadata">
<form_metadata>
<metadataver version="1.0"/>
<metadataverdate>
<date day="05" month="Jul" year="2005"/>
</metadataverdate>
<title>
<documentnbr number="2062" prefix.army="DA" scope="army" suffix=""/>
<longtitle>HAND RECEIPT/ANNEX NUMBER </longtitle>
</title>

文档继续并且从头到尾都结构良好。我正在尝试从“documentnbr”标签(从底部开始三个)中提取“number”属性。

我用来执行此操作的代码如下所示:

/***
* Locates the Document Number information in the file and returns the form number.
* @return File's self-declared number.
* @throws InvalidFormException Thrown when XPath cannot find the "documentnbr" element in the file.
*/
public String getFormNumber() throws InvalidFormException
{
try{
XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(new XFDLNamespaceContext());

Node result = (Node)xPath.evaluate(QUERY_FORM_NUMBER, doc, XPathConstants.NODE);
if(result != null) {
return result.getNodeValue();
} else {
throw new InvalidFormException("Unable to identify form.");
}

} catch (XPathExpressionException err) {
throw new InvalidFormException("Unable to find form number in file.");
}

}

其中 QUERY_FORM_NUMBER 是我的 XPath 表达式,XFDLNamespaceContext 实现了 NamespaceContext,看起来像这样:

public class XFDLNamespaceContext implements NamespaceContext {

@Override
public String getNamespaceURI(String prefix) {
if (prefix == null) throw new NullPointerException("Invalid Namespace Prefix");
else if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX))
return "http://www.PureEdge.com/XFDL/6.5";
else if ("custom".equals(prefix))
return "http://www.PureEdge.com/XFDL/Custom";
else if ("designer".equals(prefix))
return "http://www.PureEdge.com/Designer/6.1";
else if ("pecs".equals(prefix))
return "http://www.PureEdge.com/PECustomerService";
else if ("xfdl".equals(prefix))
return "http://www.PureEdge.com/XFDL/6.5";
else if ("xforms".equals(prefix))
return "http://www.w3.org/2003/xforms";
else
return XMLConstants.NULL_NS_URI;
}

@Override
public String getPrefix(String arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public Iterator getPrefixes(String arg0) {
// TODO Auto-generated method stub
return null;
}

}

我已经尝试了许多不同的 XPath 查询,但我一直觉得这应该有效:

protected static final String QUERY_FORM_NUMBER = 
"/globalpage/global/xmlmodel/xforms:instances/instance" +
"/form_metadata/title/documentnbr[number]";

不幸的是,它不起作用,我不断得到一个 null 返回值。

我读了很多书 here , here , 和 here ,但事实证明,没有任何证据足以帮助我完成这项工作。

我几乎可以肯定,当我弄清楚这一点时,我将面临困境,但对于我所缺少的东西,我真的束手无策。

感谢您通读所有内容,并提前感谢您的帮助。

-安迪

最佳答案

啊哈,我试着调试你的表达式 + 让它工作。你错过了一些事情。这个 XPath 表达式应该这样做:

/XFDL/globalpage/global/xmlmodel/instances/instance/form_metadata/title/documentnbr/@number
  1. 您需要包含根元素(在本例中为 XFDL)
  2. 出于某种原因,我并没有最终需要在表达式中使用任何命名空间。不知道为什么。如果是这种情况,则永远不会调用 NamespaceContext.getNamespaceURI()。如果我将 instance 替换为 xforms:instance,则 getNamespaceURI() 将被调用一次,并将 xforms 作为输入参数,但程序会抛出异常。
  3. 属性值的语法是@attr,而不是[attr]

我的完整示例代码:

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class XPathNamespaceExample {
static public class MyNamespaceContext implements NamespaceContext {
final private Map<String, String> prefixMap;
MyNamespaceContext(Map<String, String> prefixMap)
{
if (prefixMap != null)
{
this.prefixMap = Collections.unmodifiableMap(new HashMap<String, String>(prefixMap));
}
else
{
this.prefixMap = Collections.emptyMap();
}
}
public String getPrefix(String namespaceURI) {
// TODO Auto-generated method stub
return null;
}
public Iterator getPrefixes(String namespaceURI) {
// TODO Auto-generated method stub
return null;
}
public String getNamespaceURI(String prefix) {
if (prefix == null) throw new NullPointerException("Invalid Namespace Prefix");
else if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX))
return "http://www.PureEdge.com/XFDL/6.5";
else if ("custom".equals(prefix))
return "http://www.PureEdge.com/XFDL/Custom";
else if ("designer".equals(prefix))
return "http://www.PureEdge.com/Designer/6.1";
else if ("pecs".equals(prefix))
return "http://www.PureEdge.com/PECustomerService";
else if ("xfdl".equals(prefix))
return "http://www.PureEdge.com/XFDL/6.5";
else if ("xforms".equals(prefix))
return "http://www.w3.org/2003/xforms";
else
return XMLConstants.NULL_NS_URI;
}


}

protected static final String QUERY_FORM_NUMBER =
"/XFDL/globalpage/global/xmlmodel/xforms:instances/instance" +
"/form_metadata/title/documentnbr[number]";

public static void main(String[] args) {
try
{
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.parse(new File(args[0]));
System.out.println(extractNodeValue(doc, "/XFDL/globalpage/@sid"));
System.out.println(extractNodeValue(doc, "/XFDL/globalpage/global/xmlmodel/instances/instance/@id" ));
System.out.println(extractNodeValue(doc, "/XFDL/globalpage/global/xmlmodel/instances/instance/form_metadata/title/documentnbr/@number" ));
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}

private static String extractNodeValue(Document doc, String expression) {
try{

XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(new MyNamespaceContext(null));

Node result = (Node)xPath.evaluate(expression, doc, XPathConstants.NODE);
if(result != null) {
return result.getNodeValue();
} else {
throw new RuntimeException("can't find expression");
}

} catch (XPathExpressionException err) {
throw new RuntimeException(err);
}
}
}

关于java - XPath、XML 命名空间和 Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5465840/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com