我花了一天的時間嘗試從以下文檔中提取一個XML節點,並且無法掌握XML名稱空間的細微差別以使其工作。XPath,XML命名空間和Java
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」標籤(從底部三個)中提取「數字」屬性。
,我使用做到這一點的代碼如下所示:
/***
* 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]";
不幸的是,它不起作用,我不斷得到一個空回報。
我已經完成了相當數量的閱讀here,here和here,但沒有任何證據足以說明我的工作。
當我明白這一點時,我幾乎肯定我要面子,但我真的很機智地結束了我失蹤的事情。
感謝您閱讀所有這些內容,並提前感謝您的幫助。
-Andy
完美解決方案,我還是不太明白的命名空間,但在現在最少的代碼工作。 非常感謝。 – MrWizard54 2011-03-29 11:16:36
@Jason:「由於某種原因,我最終沒有在表達式中使用任何名稱空間。」在標準的Java實現中,默認情況下,DocumentBuilderFactory會生成namespace-_unaware_分析器。在生成DocumentBuilder之前添加'dbfac.SetNamespaceAware(true)'可能會改變結果。 – 2013-03-08 15:18:09