Java 如何在 XPath 中使用变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21258468/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use variables in XPath?
提问by Sembrano
I am using Xpath and Java.
我正在使用 Xpath 和 Java。
The XML got plenty of OBJECT_TYPES
and every object type has properties and parameters.
And each property and parameter got elements.
XML 有很多,OBJECT_TYPES
每个对象类型都有属性和参数。每个属性和参数都有元素。
How do I do the following from my XML file.
I wanna know how to select with the XPATH string expression all property elements depending on whats the name of the OBJECT_TYPE
string. The object type string name depends on what name the user selects from the list.
如何从我的 XML 文件执行以下操作。我想知道如何使用 XPATH 字符串表达式根据OBJECT_TYPE
字符串的名称选择所有属性元素。对象类型字符串名称取决于用户从列表中选择的名称。
How can I do that?
我怎样才能做到这一点?
Should be something like :
应该是这样的:
String expression = "/getObjType()/prop/*";
But the getObjectType
is a method so I cant use it in a string expression.
但这getObjectType
是一种方法,所以我不能在字符串表达式中使用它。
XML looks something like this:
XML 看起来像这样:
<type>
<OBJECT_TYPE>SiteData</OBJECT_TYPE>
<prop>
<DESCRIPTION>Site parameters</DESCRIPTION>
<PARENT>NULL</PARENT>
<VIRTUAL>0</VIRTUAL>
<VISIBLE>1</VISIBLE>
<PICTURE>NULL</PICTURE>
<HELP>10008</HELP>
<MIN_NO>1</MIN_NO>
<MAX_NO>1</MAX_NO>
<NAME_FORMAT>NULL</NAME_FORMAT>
</prop>
<param>
<PARAMETER>blabla</PARAMETER>
<DATA_TYPE>INTEGER</DATA_TYPE>
<DESCRIPTION>blaba</DESCRIPTION>
<MIN_NO>1</MIN_NO>
<MAX_NO>1</MAX_NO>
<ORDER1>1</ORDER1>
<NESTED>0</NESTED>
<DEFAULT1>NULL</DEFAULT1>
<FORMAT>0:16382</FORMAT>
</param>
<OBJECT_TYPE>Data</OBJECT_TYPE>
<prop>
<DESCRIPTION>Site parameters</DESCRIPTION>
<PARENT>NULL</PARENT>
<VIRTUAL>0</VIRTUAL>
<VISIBLE>1</VISIBLE>
<PICTURE>NULL</PICTURE>
<HELP>10008</HELP>
<MIN_NO>1</MIN_NO>
<MAX_NO>1</MAX_NO>
<NAME_FORMAT>NULL</NAME_FORMAT>
</prop>
<param>
<PARAMETER>gmgm</PARAMETER>
<DATA_TYPE>INTEGER</DATA_TYPE>
<DESCRIPTION>babla</DESCRIPTION>
<MIN_NO>1</MIN_NO>
<MAX_NO>1</MAX_NO>
<ORDER1>1</ORDER1>
<NESTED>0</NESTED>
<DEFAULT1>NULL</DEFAULT1>
<FORMAT>0:16382</FORMAT>
</param>
</type>
So depending on whats the name of the Object_type I wanna get thoose properties and I have list 122 object types so I have to use a varible to pick which one the user selects.
因此,根据 Object_type 的名称,我想获得 thoose 属性,并且我列出了 122 个对象类型,因此我必须使用一个变量来选择用户选择的对象类型。
public class PropXMLParsing {
static PropXMLParsing instance = null;
private List<String> list = new ArrayList<String>();
ObjType obj = new ObjType();
public static PropXMLParsing getInstance() {
if (instance == null) {
instance = new PropXMLParsing();
try {
instance.ParserForObjectTypes();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
return instance;
}
public void ParserForObjectTypes() throws SAXException, IOException,
ParserConfigurationException {
try {
FileInputStream file = new FileInputStream(new File(
"xmlFiles/CoreDatamodel.xml"));
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
builderFactory.setNamespaceAware(true);
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xp = XPathFactory.newInstance().newXPath();
final Map<String, Object> vars = new HashMap<String, Object>();
xp.setXPathVariableResolver(new XPathVariableResolver() {
public Object resolveVariable(QName name) {
return vars.get(name.getLocalPart());
}
});
XPathExpression expr = xp
.compile("/type/OBJECT_TYPE[. = $type]/following-sibling::prop[1]");
vars.put("type", obj.getObjectType());
NodeList objectProps = (NodeList) expr.evaluate(xmlDocument,
XPathConstants.NODESET);
System.out.println(objectProps);
for (int i = 0; i < objectProps.getLength(); i++) {
System.out.println(objectProps.item(i).getFirstChild()
.getNodeValue());
list.add(objectProps.item(i).getFirstChild().getNodeValue());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
public String convertListToString() {
StringBuilder sb = new StringBuilder();
if (list.size() > 0) {
sb.append(list.get(0));
for (int i = 1; i < list.size(); i++) {
sb.append(list.get(i));
}
}
return sb.toString();
}
}
Second solution I have tried that aint working neither not printing out anything in the console.
第二个解决方案我尝试过,既不能在控制台中打印出任何内容,也不能正常工作。
public void ParserForObjectTypes() throws SAXException, IOException,
ParserConfigurationException {
try {
FileInputStream file = new FileInputStream(new File(
"xmlFiles/CoreDatamodel.xml"));
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodeList = (NodeList) xPath.compile(
"//OBJECT_TYPE[text() = '" + obj.getObjectType()
+ "']/following-sibling::prop[1]/*").evaluate(
xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
System.out.println(nodeList.item(i).getNodeName() + " = "
+ nodeList.item(i).getTextContent());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
采纳答案by Nick Holt
This XPATH will select all the elements within the prop
element that follows the OBJECT_TYPE
with the text SiteData
:
这XPATH将选择范围内的所有元素prop
后面的元素OBJECT_TYPE
与文本SiteData
:
//OBJECT_TYPE[text() = 'SiteData']/following-sibling::prop[1]/*
To change the OBJECT_TYPE
being selected just construct the XPATH in the code:
要更改OBJECT_TYPE
被选中的对象,只需在代码中构建 XPATH:
String xpath = "//OBJECT_TYPE[text() = '" + getObjType() + "']/following-sibling::prop[1]/*"
Which results in code like this:
结果是这样的代码:
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodeList = (NodeList)xPath.compile("//OBJECT_TYPE[text() = '" + getObjType() + "']/following-sibling::prop[1]/*").evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++)
{
System.out.println(nodeList.item(i).getNodeName() + " = " + nodeList.item(i).getTextContent());
}
That given the XML from the question and when getObjType()
returns SiteData
prints:
给出问题中的 XML 以及何时getObjType()
返回SiteData
打印:
DESCRIPTION = Site parameters
PARENT = NULL
VIRTUAL = 0
VISIBLE = 1
PICTURE = NULL
HELP = 10008
MIN_NO = 1
MAX_NO = 1
NAME_FORMAT = NULL
回答by Ian Roberts
If you want to extract the prop
belonging to a specific OBJECT_TYPE
you can do that with
如果你想提取prop
属于特定的OBJECT_TYPE
你可以这样做
/type/OBJECT_TYPE[. = 'some type']/following-sibling::prop[1]
In Java you could build up this XPath expression dynamically using string concatenation but it would be much safer to use an XPath variable if the library you're using can support that (you don't say in the question what library you're using). For example with javax.xml.xpath
在 Java 中,您可以使用字符串连接动态构建此 XPath 表达式,但如果您使用的库可以支持,则使用 XPath 变量会更安全(您没有在问题中说明您使用的是哪个库) . 例如与javax.xml.xpath
XPath xp = XPathFactory.newInstance().newXPath();
final Map<String, Object> vars = new HashMap<String, Object>();
xp.setXPathVariableResolver(new XPathVariableResolver() {
public Object resolveVariable(QName name) {
return vars.get(name.getLocalPart());
}
});
XPathExpression expr = xp.compile("/type/OBJECT_TYPE[. = $type]/following-sibling::prop[1]");
vars.put("type", "Data");
Node dataProps = (Node)expr.evaluate(doc, XPathConstants.NODE);
vars.put("type", "SiteData");
Node siteProps = (Node)expr.evaluate(doc, XPathConstants.NODE);
// taking the value from a variable
vars.put("type", obj.getObjectType());
Node objectProps = (Node)expr.evaluate(doc, XPathConstants.NODE);