使用给定的xpath列表仅保留xml中的所需元素

时间:2014-08-04 09:51:25

标签: java xml dom xslt xpath

我有一些复杂的xml结构。有时我想只保留与xpath条目的运行时列表匹配的元素。

示例xml


 <Employee>
    <Address>
        <addressLine1>Dummy Line 1</addressLine1>
        <zip>535270</zip>
    </Address>
    <Department>
        <id>102</id>
        <name>development</name>
    </Department
</Employee>

示例xpath条目可能有点像

//Employee/Address
//Employee/Department/
//Employee/Department/name

在上面的xpath中,如果你观察到我们在部门内部有Department和Name,那么在这种情况下我可以忽略Department.Also上面的xpath条目也可以如下所示

//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中有没有更好的选择?

1 个答案:

答案 0 :(得分:0)

我必须承认我并不完全理解你的要求,但我所看到的是:

  • 你有一套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,就像您的示例中的那个。我删除了尾随//,只是在当前路径与任何路径匹配时进行匹配(考虑到隐含的后代或自我,如示例所示)。

您可能希望将for-expression包装在函数中,并调用该函数将当前路径的串联映射到列表中的任何路径。

在当前形式中,您还需要提供通向更深路径的路径,或者您还必须实现fn:snapshot-like function来复制祖先节点。

无论如何,我认为这是一种模仿的方法,不一定是xsl:evaluate,而是模仿基于路径的模式匹配,正如你的问题似乎暗示的那样。