Java 使用给定的xpath列表在xml中只保留所需的元素
我有一些复杂的xml结构。有时,我只想让元素与xpath条目的运行时列表相匹配 示例xml 在上面的xpath中,如果您观察到我们在Department中有Department和Name,那么在这种情况下,我可以忽略DepartmentJava 使用给定的xpath列表在xml中只保留所需的元素,java,xml,dom,xslt,xpath,Java,Xml,Dom,Xslt,Xpath,我有一些复杂的xml结构。有时,我只想让元素与xpath条目的运行时列表相匹配 示例xml 在上面的xpath中,如果您观察到我们在Department中有Department和Name,那么在这种情况下,我可以忽略Department //Employee/Address //Employee/Department/name 我想要的结果xml如下 <Employee> <Address> <addressLine1>Dummy L
//Employee/Address
//Employee/Department/name
我想要的结果xml如下
<Employee>
<Address>
<addressLine1>Dummy Line 1</addressLine1>
<zip>535270</zip>
</Address>
<Department>
<name>development</name>
</Department
</Employee>
我意识到我可以通过xslt实现这一点。所以我想要xslt来满足这种通用需求。我当前的代码也是用java编写的。java中有更好的替代方案吗?我不得不承认,我并不完全理解您的需求,但我看到的是: 您有一组XPath 如果将这些XPath语句应用于输入文档,您似乎希望得到它们的并集 与XPath联合表达式一样删除重复项 某些元素即使不在XPath语句列表中,也可能会出现。 我最初的反应是:使用xsl:evaluate,但考虑到您正在生成所有XPath表达式,这可能不会给出您想要的结果。此外,它还需要一个XSLT 3.0处理器 使用XSLT 2.0,您可以执行以下操作:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" />
<xsl:variable name="patterns" as="xs:string*">
<xsl:sequence select="(
'foo/bar',
'foo/test',
'foo/bar/zed')" />
</xsl:variable>
<xsl:template match="node()[true() = (
for $p in $patterns
return ends-with(
string-join(current()/ancestor-or-self::*/name(),
'/'), $p))]">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
这只是为了让你开始,而不是作为一个全面的解决方案。它匹配产品//QName/QName的XPath,如您的示例中所示。我删除了尾随的//,并在当前路径匹配任何路径时简单地进行匹配,同时考虑隐式后代或self,如您的示例所示
您可能希望将for表达式包装在函数中,并调用该函数以将当前路径的串联映射到列表中的任何路径
在其当前形式中,您还需要提供通向更深路径的路径,或者您必须实现一个复制祖先节点的方法
无论如何,我认为这是一种足够简单的方法,不一定模仿xsl:evaluate,而是模仿基于路径的模式匹配,正如您的问题所暗示的那样。我意识到我可以通过xslt实现这一点。但是,如果路径在运行时以字符串形式传递,则不容易。您能否更详细地解释为什么addressLine和zip会出现在输出中,尽管没有与它们匹配的路径?为什么id被删除而zip没有?addressLine和zip出现是因为地址存在,并且没有其他排除项存在。我得到的是唯一的叶子elements@mohan,这就是为什么我以当前的形式写,你还需要提供通向更深层路径的路径,或者,您必须实现类似于fn:snapshot的函数来复制祖先节点。。这是很自然的,因为你无法匹配你不知道的东西——祖先不匹配模式,直到在更深层次上。
<Employee>
<Address>
<addressLine1>Dummy Line 1</addressLine1>
<zip>535270</zip>
</Address>
<Department>
<name>development</name>
</Department
</Employee>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" />
<xsl:variable name="patterns" as="xs:string*">
<xsl:sequence select="(
'foo/bar',
'foo/test',
'foo/bar/zed')" />
</xsl:variable>
<xsl:template match="node()[true() = (
for $p in $patterns
return ends-with(
string-join(current()/ancestor-or-self::*/name(),
'/'), $p))]">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>