本文将介绍如何使用XPath在Java中使用名称空间查询XML?的详细情况,特别是关于xpath命名空间的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些
本文将介绍如何使用XPath在Java中使用名称空间查询XML?的详细情况,特别是关于xpath 命名空间的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于Java XML使用方法-使用xpath在XML文件中的节点列表中查找和添加/替换更多子节点、Java XPath:使用默认名称空间xmlns的查询、java – VTD-XML大数据xPathExpression不使用名称空间、java – 使用XmlPullParser处理Xml名称空间的知识。
本文目录一览:- 如何使用XPath在Java中使用名称空间查询XML?(xpath 命名空间)
- Java XML使用方法-使用xpath在XML文件中的节点列表中查找和添加/替换更多子节点
- Java XPath:使用默认名称空间xmlns的查询
- java – VTD-XML大数据xPathExpression不使用名称空间
- java – 使用XmlPullParser处理Xml名称空间
如何使用XPath在Java中使用名称空间查询XML?(xpath 命名空间)
当我的XML看起来像这样(no xmlns
)时,我可以使用XPath轻松查询它/workbook/sheets/sheet[1]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook> <sheets> <sheet name="Sheet1" sheetId="1" r:id="rId1"/> </sheets></workbook>
但是当看起来像这样我就不能
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> <sheets> <sheet name="Sheet1" sheetId="1" r:id="rId1"/> </sheets></workbook>
有任何想法吗?
答案1
小编典典在第二个示例XML文件中,元素绑定到名称空间。你的XPath尝试处理绑定到默认“无名称空间”名称空间的元素,因此它们不匹配。
首选方法是使用名称空间前缀注册名称空间。它使你的XPath更加易于开发,读取和维护。
但是,并不一定要注册名称空间并在XPath中使用名称空间前缀。
你可以公式化一个XPath表达式,该表达式对元素使用通用匹配,并使用谓词过滤器来限制所需local-name()
和的匹配namespace-uri()
。例如:
/*[local-name()=''workbook'' and namespace-uri()=''http://schemas.openxmlformats.org/spreadsheetml/2006/main''] /*[local-name()=''sheets'' and namespace-uri()=''http://schemas.openxmlformats.org/spreadsheetml/2006/main''] /*[local-name()=''sheet'' and namespace-uri()=''http://schemas.openxmlformats.org/spreadsheetml/2006/main''][1]
如你所见,它会产生一个非常冗长且冗长的XPath语句,该语句很难读取(和维护)。
你也可以只匹配local-name()
元素的,而忽略名称空间。例如:
/*[local-name()=''workbook'']/*[local-name()=''sheets'']/*[local-name()=''sheet''][1]
但是,你冒着匹配错误元素的风险。如果你的XML混合使用了相同的词汇表(对于该实例而言可能不是问题)local-name()
,则你的XPath可能匹配错误的元素并选择了错误的内容:
Java XML使用方法-使用xpath在XML文件中的节点列表中查找和添加/替换更多子节点
Xpath专门用于跟踪/读取xml,但不能用于修改xml。
因此,我将代码从使用XPath更改为使用DOM Parser。
try
{
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
// Map root element
Element rootElement = doc.createElement("map");
doc.appendChild(rootElement);
//ROOT map
//1. ankomstDato
Element ankomstDato = doc.createElement("string");
Attr attrType_ankomstDato = doc.createAttribute("key");
attrType_ankomstDato.setValue("ankomstDato");
ankomstDato.setAttributeNode(attrType_ankomstDato);
ankomstDato.appendChild(doc.createTextNode(ankomstDato_value));
rootElement.appendChild(ankomstDato);
//. planlagtAntallPerUndergruppe
// planlagtAntallPerUndergruppe element
if (planlagtAntallPerUndergruppe_Count !=0){
Element planlagtAntallPerUndergruppe = doc.createElement("array");
rootElement.appendChild(planlagtAntallPerUndergruppe);
Attr attr = doc.createAttribute("key");
attr.setValue("planlagtAntallPerUndergruppe");
planlagtAntallPerUndergruppe.setAttributeNode(attr);
for (int i = 0; i < planlagtAntallPerUndergruppe_Count; i ++){
//to add "map" element
Element map1 = doc.createElement("map");
planlagtAntallPerUndergruppe.appendChild(map1);
// antall element
Element antall = doc.createElement("number");
Attr attrType = doc.createAttribute("key");
attrType.setValue("antall");
antall.setAttributeNode(attrType);
antall.appendChild(doc.createTextNode(planlagtAntallPerUndergruppe_antall_value[i]));
map1.appendChild(antall);
//kode element
Element kode = doc.createElement("string");
Attr attrType1 = doc.createAttribute("key");
attrType1.setValue("kode");
kode.setAttributeNode(attrType1);
kode.appendChild(doc.createTextNode(planlagtAntallPerUndergruppe_kode_value[i]));
map1.appendChild(kode);
}
}
//end planlagtAntallPerUndergruppe
// Write the content into XML file
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("E:/utils/students-new.xml"));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
// Beautify the format of the resulted XML
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4");
transformer.transform(source,result);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
,
将收集的数组作为参数传递到Write2XMLfile
方法中
public void Write2XMLfile(String[] planlagtAntallPerUndergruppe_antall_value,String[] planlagtAntallPerUndergruppe_kode_value) {
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.newDocument();
Element rootElement = doc.createElement("map");
doc.appendChild(rootElement);
Element mainString = doc.createElement("string");
mainString.setAttribute("key","ankomstDato");
rootElement.appendChild(mainString).setTextContent("2020-08-20");
Element array = doc.createElement("array");
array.setAttribute("key","planlagtAntallPerUndergruppe");
rootElement.appendChild(array);
if(planlagtAntallPerUndergruppe_antall_value.length>0){
for (int i = 0; i < planlagtAntallPerUndergruppe_antall_value.length; i++) {
Element map = doc.createElement("map");
array.appendChild(map);
Element number = doc.createElement("number");
number.setAttribute("key","antall");
map.appendChild(number).setTextContent(planlagtAntallPerUndergruppe_antall_value[i]);
Element string = doc.createElement("string");
string.setAttribute("key","kode");
map.appendChild(string).setTextContent(planlagtAntallPerUndergruppe_kode_value[i]);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT,"yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","2");
DOMSource source = new DOMSource(doc);
StreamResult output = new StreamResult(new File("output.xml"));
transformer.transform(source,output);
} catch (Exception e) {
e.printStackTrace();
}
}
output.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<map>
<string key="ankomstDato">2020-08-20</string>
<array key="planlagtAntallPerUndergruppe">
<map>
<number key="antall">67</number>
<string key="kode">SLAKTEGRIS</string>
</map>
<map>
<number key="antall">4</number>
<string key="kode">UNGSAU</string>
</map>
</array>
</map>
Java XPath:使用默认名称空间xmlns的查询
我要对此文件执行XPath查询(显示的摘录):
<?xml version="1.0" encoding="UTF-8"?><!-- MetaDataAPI generated on: Friday, May 25, 2007 3:26:31 PM CEST --><ModelClass xmlns="http://xml.sap.com/2002/10/metamodel/webdynpro" xmlns:IDX="urn:sap.com:WebDynpro.ModelClass:2.0"> <ModelClass.Parent> <Core.Reference package="com.test.mypackage" name="ModelName" type="Model"/>
这是我正在使用的代码的摘要:
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = domFactory.newDocumentBuilder();Document document = builder.parse(new File(testFile));XPathFactory factory = XPathFactory.newInstance();XPath xpath = factory.newXPath();xpath.setNamespaceContext( new NamespaceContext() { public String getNamespaceURI(String prefix) {...String result = xpath.evaluate(xpathQueryString, document);System.out.println(result);
我面临的问题是,在XPath查询中引用默认名称空间时,不会调用getNamespaceURI方法来解决它。例如,此查询不提取任何内容:
//xmlns:ModelClass.Parent/xmlns:Core.Reference[@type=\"Model\"]/@package
现在,我尝试通过用xmlns
假前缀替换来“诱骗”解析器d
,然后相应地编写getNamespaceURI
方法(以便http://xml.sap.com/2002/10/metamodel/webdynpro
在d
遇到问题时返回)。在这种情况下,将getNamespaceURI
调用,但是XPath表达式求值的结果始终是一个空字符串。
如果我从文件和XPath查询表达式中删除名称空间,则可以获得所需的字符串(com.test.mypackage)。
有没有办法使默认名称空间正常工作?
答案1
小编典典在您的Namespace
上下文中,将您选择的前缀(例如df
)绑定到文档中的名称空间URI
xpath.setNamespaceContext( new NamespaceContext() { public String getNamespaceURI(String prefix) { switch (prefix) { case "df": return "http://xml.sap.com/2002/10/metamodel/webdynpro"; ... } });
然后在路径表达式中使用该前缀来限定元素名称,例如/df:ModelClass/df:ModelClass.Parent/df:Core.Reference[@type= ''Model'']/@package
。
java – VTD-XML大数据xPathExpression不使用名称空间
更改为删除不可行的代码
try { //without namespace works VTDGen vtdGen = new VTDGen(); vtdGen.parseFile("test.xml",false); VTDNav vtdNav = vtdGen.getNav(); Autopilot autopilot = new Autopilot(vtdNav); autopilot.selectXPath("//Receiver/Identifier"); autopilot.evalXPath(); System.out.println("Stand===>" + vtdNav.getXPathStringVal() + " ===>"); } catch(indexoutofboundsexception e) { e.printstacktrace(); } try { //with namespace doesn't work VTDGen vtdGen = new VTDGen(); vtdGen.parseFile("test.xml",true); VTDNav vtdNav = vtdGen.getNav(); Autopilot autopilot = new Autopilot(vtdNav); autopilot.declareXPathNameSpace("x","http://test/namespaces/ssfgf"); autopilot.selectXPath("//x:Receiver/Identifier"); int index = autopilot.evalXPath(); System.out.println("Stand NS ===>" + vtdNav.toString(index) + " ===>"); } catch(indexoutofboundsexception e) { e.printstacktrace(); } try { //without namespace doesn't work VTDGenHuge vg = new VTDGenHuge(); vg.parseFile("test.xml",false); VTDNavHuge vn = vg.getNav(); AutopilotHuge ap = new AutopilotHuge(vn); ap.selectXPath("//Receiver/Identifier"); ap.evalXPath(); System.out.println("Huge ===> " + vn.toString(vn.getText()) + " ===>"); } catch(indexoutofboundsexception e) { e.printstacktrace(); } try { //with namespace doesn't work VTDGenHuge vg = new VTDGenHuge(); vg.parseFile("test.xml",true); VTDNavHuge vn = vg.getNav(); AutopilotHuge ap = new AutopilotHuge(vn); ap.declareXPathNameSpace("x","http://test/namespaces/ssfgf"); ap.selectXPath("//Receiver/Identifier"); ap.evalXPath(); System.out.println("Huge NS ===> " + vn.toString(vn.getText()) + " ===>"); } catch(indexoutofboundsexception e) { e.printstacktrace(); }
我得到了巨大的代码和NS标准的java.lang.indexoutofboundsexception
这是一个样本XML,遗憾的是无法显示真正的xml
<x:TestDocument xmlns:x="http://test/namespaces/ssfgf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://test/namespaces/ssfgf"> <x:TestHeader> <x:Type></x:Type> <x:Scopes> <x:Scope> <x:Identifier>Context</x:Identifier> <x:Type>CaseId</x:Type> <x:InstanceIdentifier>case1</x:InstanceIdentifier> <x:Business> <x:Name>businessnane1</x:Name> </x:Business> </x:Scope> <x:Scope> <x:Identifier>Context</x:Identifier> <x:InstanceIdentifier>test1</x:InstanceIdentifier> <x:Type>TestId</x:Type> </x:Scope> <x:Scope> <x:Identifier>Context</x:Identifier> <x:InstanceIdentifier>other1</x:InstanceIdentifier> <x:Type>OtherId</x:Type> </x:Scope> </x:Scopes> <x:Receiver> <x:Identifier>testreceiverid</x:Identifier> </x:Receiver> <x:DocumentIdentification> <x:Type>type1</x:Type> <x:Identifier>id1</x:Identifier> <x:TypeVersion>version1</x:TypeVersion> </x:DocumentIdentification> </x:TestHeader> <x:TestBody attribute1="attribute1" attribute2="attribute2"> <TestingData>testingdata1</TestingData> </x:TestBody> </x:TestDocument>
解决方法
首先,你没有使用VTD的第二个代码片段来启用命名空间感知.
您也没有设置名称空间绑定权限..
ap.declareXPathNameSpace("x","http://test/namespaces/ssfgf");
第三,getText()返回-1,这导致异常.
最后,// test将不匹配任何节点…所以getText()肯定会返回-1.
java – 使用XmlPullParser处理Xml名称空间
这里我使用XmlPullParser来解析下面的文档.由于命名空间,它不起作用,我如何解析命名空间?
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(in, HTTP.UTF_8);
String namespace = xpp.getNamespace();
boolean inMessage = false;
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
//START TAGS
if(eventType == XmlPullParser.START_TAG) {
if(xpp.getName().equals(namespace+"resource")) {
httpCode = Integer.valueOf( xpp.getAttributeValue(null, "code").trim() );
type = xpp.getAttributeValue(null, "type").trim();
} else if(xpp.getName().equals(namespace+"message")) {
inMessage = true;
}
//TAG TEXT
} else if(eventType == XmlPullParser.TEXT) {
if(inMessage) {
message = xpp.getText().trim();
break; //CANCEL the iteration
}
} else if(eventType == XmlPullParser.END_TAG) {
if(inMessage) {
inMessage = false;
}
}
eventType = xpp.next();
}
这是我要解析的文档类型的示例
<?xml version="1.0" encoding="UTF-8"?>
<res:resource
xmlns:res="http://www.example.com/ns/server/resource"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.com/ns/server/resource resource.xsd "
version="1" >
<res:message httpCode="200" type="ok" >
<![CDATA[Sample Success Response]]>
</res:message>
<dif:person
xmlns:dif="http://www.example.com/ns/server/resource"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.com/ns/server/person person.xsd "
version="1" >
<dif:name>test name</dif:name>
<dif:description lang="en">test description</dif:description>
</dif:person >
</res:resource>
我想分别解析res和dif.
解决方法:
您可以通过调用getPrefix方法来区分它们.一些测试代码:
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
InputStream input = getResources().openRawResource(R.raw.test);
parser.setInput(input, HTTP.UTF_8);
int eventType = parser.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG){
String prefix = parser.getPrefix();
String name = parser.getName();
Log.i("XML", String.format("prefix=%s,name=%s",prefix,name));
if( "dif".equals(prefix)){
handleDiff(parser);
}else if ("res".equals(prefix)){
handleRes(parser);
}
}
eventType = parser.next();
}
} catch (Exception e) {
Log.e("XML","",e);
}
Logcat输出你的测试数据:
prefix=res,name=resource
prefix=res,name=message
prefix=dif,name=person
prefix=dif,name=name
prefix=dif,name=description
今天关于如何使用XPath在Java中使用名称空间查询XML?和xpath 命名空间的讲解已经结束,谢谢您的阅读,如果想了解更多关于Java XML使用方法-使用xpath在XML文件中的节点列表中查找和添加/替换更多子节点、Java XPath:使用默认名称空间xmlns的查询、java – VTD-XML大数据xPathExpression不使用名称空间、java – 使用XmlPullParser处理Xml名称空间的相关知识,请在本站搜索。
本文标签: