在XPath表达式中使用条件
我需要解析数据库中的XML文档并搜索其中的给定表达式。然后,如果给定的表达式存在于XML中,我必须返回一个String值,否则我需要通过下一个表达式解析并返回另一个String值等等。在XPath表达式中使用条件
// An xml document is passed as a Node when getEntryType() method is called
public static class XMLTextFields {
public static String getEntryType(Node target) throws XPathExpressionException {
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXpath();
String entryType = null;
String [] expression = new String [] {"./libx:package", "./libx:libapp", "./libx:module"};
String [] type = new String [] {"Package", "Libapp", "Module" };
for (int i = 0; i < 3; i ++) {
XPathExpression expr = xpath.compile(expression[i]);
Object result = expr.evaluate(target, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
if (nodes.getLength() == 0)
continue;
entryType = (type[i]);
}
return entryType;
}
}
我想知道是否有一个更简单的方式做到这一点:
我用下面的代码实现这一点?意思是,有没有一种方法可以像使用“表达式”一样的函数返回一个字符串,如果表达式存在于xml中的话。
我猜我应该可以做这样的事情,但我不能完全确定:如果libx中
String [] Expression = new String [] {"[./libx:package]\"Package\"", ....}
意义,回归“大礼包”:在给定的XML存在包节点
@ALL:谢谢!
我使用:
XPathExpression EXPR = xpath.compile( “CONCAT(子串( '包',0100 *布尔型(// libx中:封装)),” +“的子串( 'Libapp',0100 *布尔(// libx中:libapp)),子( '模块',0100 *布尔型(// libx中:模块)))“); expr.evaluate(target,XPathConstants.STRING);
是有,只是在你的表达式中使用XPath函数:
Expression exp = xpath.compile("local-name(*[local-name() = 'package'])")
// will return "package" for any matching elements
exp.evaluate(target, XPathConstants.STRING);
但这将返回,而不是“包”,“包”。注意大写的P
下面是测试代码:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.util.Map;
import java.util.HashMap;
public class Test {
private static Map<String, String> mappings = new HashMap<String, String>();
static {
mappings.put("package", "Package");
mappings.put("libapp", "Application");
mappings.put("module", "Module");
}
public static void main(String[] args) throws Throwable {
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
String entryType = null;
XPathExpression [] expressions = new XPathExpression[] {
xpath.compile("local-name(*[local-name() = 'package'])"),
xpath.compile("local-name(*[local-name() = 'libapp'])"),
xpath.compile("local-name(*[local-name() = 'module'])")
};
DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
DocumentBuilder parser = fac.newDocumentBuilder();
Document doc = parser.parse(args[0]);
for(int i = 0; i < expressions.length; i++) {
String found = (String) expressions[i].evaluate(doc.getDocumentElement(),
XPathConstants.STRING);
entryType = mappings.get(found);
if(entryType != null && !entryType.trim().isEmpty()) {
break;
}
}
System.out.println(entryType);
}
}
文本文件的内容:
<?xml version="1.0"?>
<root xmlns:libx="urn:libex">
<libx:package>mypack</libx:package>
<libx:libapp>myapp</libx:libapp>
<libx:module>mymod</libx:module>
</root>
谢谢!我的xml文档包含libx:package,libx:libapp或libx:module(NOT ALL THREE)。所以,当local-name()函数返回空时,我会继续,否则我会从循环中断开。现在,entryType字符串将具有适当的字符串。 但是,字符串entryType应该是“Package”而不是“package”。 (注意大写P)。这是必要的!有没有办法做到这一点?请在下面的评论中看到我的测试代码: – sony 2010-08-04 16:46:00
getEntryType(..){........ String [] expression = new String [] {“local-name(* [local-name()=' (local name)(* [local-name()='module'])“};对于(int i = 0; i
您的代码似乎是正确的,但不需要在每次调用该方法时编译表达式。我已经更新了代码以返回一个不同的字符串,如果找到一个元素。我已经将元素名称映射到“用户firendly名称”。 – naikus 2010-08-04 17:53:17
你可以在这里使用XSLT。在XSLT您可以使用
<xsl:value-of select="*[starts-with(name(),'libx:package')]" />
检查节点名,也可以使用检查
<xsl:if select="name()='libx:package'" > <!-- Your cusotm elements here... --> </xsl:if>
您可以检查元素的存在和属性这种方式来验证特定需求。
希望这有助于。
在XPath 1.0
concat(translate(substring(local-name(libx:package|libx:libapp|libx:module),
1,
1),
'plm',
'PLM'),
substring(local-name(libx:package|libx:libapp|libx:module),2))
编辑:这是难治,因为没有提供输入样本了解路径...
我正在使用XPath处理器版本1,所以这似乎是最合适的。 – sony 2010-09-21 03:57:24