【问题标题】:keep only wanted elements in xml with the given list of xpath在给定的 xpath 列表中只保留 xml 中想要的元素
【发布时间】:2014-08-04 09:51:25
【问题描述】:

我有一些复杂的 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 中,如果您发现我们在部门内有部门和名称,那么在这种情况下,我可以忽略部门。此外,上面的 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有没有更好的选择??

【问题讨论】:

  • "我意识到我可以通过 xslt 实现这一点。" 但是,如果路径在运行时作为字符串传递,这并不容易。跨度>
  • 您能否更详细地解释为什么addressLinezip 出现在输出中,尽管没有与它们匹配的路径?为什么id 被删除而zip 没有被删除?
  • addressLine 和 zip 出现,因为 Address 存在且不存在其他排除项

标签: java xml dom xslt xpath


【解决方案1】:

我不得不承认我没有完全理解你的要求,但我看到的是:

  • 你有一组 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 表达式包装在一个函数中并调用该函数以将当前路径的串联映射到列表中的任何路径。

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

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

【讨论】:

  • 有了这个我只得到叶子元素
  • @mohan,这就是我写 “在当前形式中,您还需要提供通向更深路径的路径,或者您必须实现 fn:snapshot-类似的功能也可以复制祖先节点。”.这是很自然的,因为你无法匹配你不知道的东西(祖先不匹配模式,直到更深层次)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 2016-04-07
相关资源
最近更新 更多