我试图找到遵循以下两条规则的所有元素名称。
1
。元素应该有<set>erase</set>
2。如果两个或多个元素在层次结构中具有<set>erase</set>
(例如:<b>
和<d>
都具有<set>erase</set>
),那么只需要打印父节点名称(即{{ 1}}在这种情况下)。
因此,xml以下所需的结果必须是:
b,y,p
<b>
当我使用<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a>
<b>
<set>erase</set>
<d>
<set>erase</set>
</d>
</b>
<c>
<x>
</x>
</c>
<e>
<y>
<set>erase</set>
<q>
</q>
</y>
<z>
<p>
<set>erase</set>
</p>
</z>
</e>
</a>
时,我只在结果集中获得节点query = (//set[contains(.,'erase')])[1]
当我使用b
时,我在结果集中获取所有nodesList query = //set[contains(.,'erase')]
。
任何人都可以帮我找到导致nodeList b,d,y,p
,b
和y
的查询。
这是我使用的java代码片段。
p
输出:
XPath xpath = factory.newXPath();
String query = "//set[contains(.,'erase')]";
XPathExpression expr=null;
try {
expr = xpath.compile(query);
} catch (XPathExpressionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Object result = null;
try {
result = expr.evaluate(doc, XPathConstants.NODESET);
} catch (XPathExpressionException e) {
e.printStackTrace();
}
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
String x = "";
Node n = nodes.item(i).getParentNode();
x=n.getNodeName();
while(!n.getNodeName().equalsIgnoreCase(request.getClass().getSimpleName())){
if ((n = n.getParentNode())!=null){
x=n.getNodeName()+"."+x;
}
}
System.out.println("Path: "+x);
任何人都可以帮我找出仅导致a.b
a.b.d
a.e.y
a.e.z.p
的查询
如果您需要更多详细信息,请告诉我们。或任何其他用例。
答案 0 :(得分:1)
一个完全选择所需元素的表达式是:
//*[set[. = 'erase' and not(node()[2])]
and
not(ancestor::*
[set
[. = 'erase' and not(node()[2])]
]
)
]
基于XSLT的验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select=
"//*[set[. = 'erase' and not(node()[2])]
and
not(ancestor::*
[set
[. = 'erase' and not(node()[2])]
]
)
]">
<xsl:value-of select="name()"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
此转换适用于Sean B. Durkin XML文档提供的:
<a>
<b>
<set>erase</set>
<set>
<a/>erase
</set>
<d>
<set>erase</set>
</d>
</b>
<c>
<x> </x>
</c>
<e>
<y>
<set>erase</set>
<q> </q>
</y>
<z>
<p>
<set>erase</set>
</p>
</z>
</e>
</a>
评估上面的XPath表达式并输出所选元素的名称 - 生成所需的正确结果:
b
y
p
请注意以下两个表达式非常不正确:
*[set[text()='erase']][not(ancestor::*[set[text()='erase']])]
或者:
*[set[text()='erase']][ancestor::*[set[text()!='erase']]]
这两个表达式存在多个问题:
它们是相对表达式,无论它们应用于哪个初始上下文,它们都无法选择层次结构中具有未定义深度和结构的所有想要元素。
set[text()='erase']
不仅会选择表单元素:
...
<set>erase</set>
还有表格的元素:
<set>
xyz
<a/>erase</set>
0.3。类似地:
set[text()!='erase']
选择表单元素:
<set>
xyz
<a/>erase</set>
答案 1 :(得分:0)
这是我的第二次尝试:
//*[ set[count(node())=1 and text()='erase'] and
not( ancestor::*[ set[count(node())=1 and text()='erase']])
]
此选择通过了我第一个答案中显示的测试用例。
答案 2 :(得分:-1)
以下XPath选择所需的节点:
//*[set[text()='erase']][not(ancestor::*[set[text()='erase']])]
我使用以下样式表进行了测试
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="@*|text()" />
<xsl:template match="//*[set[text()='erase']][not(ancestor::*[set[text()='erase']])]">
<xsl:text>(</xsl:text>
<xsl:for-each select="self::*|ancestor::*">
<xsl:value-of select="name()"/>
<xsl:text>.</xsl:text>
</xsl:for-each>
<xsl:text>) </xsl:text>
</xsl:template>
</xsl:stylesheet>
它产生了输出
(a.b.) (a.e.y.) (a.e.z.p.)
答案 3 :(得分:-1)
或者这个关于Harpo答案的轻微调整?:
*[set[text()='erase']][ancestor::*[set[text()!='erase']]]
根据我对Novatchev答案的评论,请考虑有用的测试用例:
这是对问讯者演示文档的更改。我添加了另一个节点。
<?xml version="1.0"?>
<a>
<b>
<set>erase</set>
<set><a/>erase</set>
<d>
<set>erase</set>
</d>
</b>
<c>
<x>
</x>
</c>
<e>
<y>
<set>erase</set>
<q>
</q>
</y>
<z>
<p>
<set>erase</set>
</p>
</z>
</e>
</a>
答案应该是
b
y
p