【问题标题】:Get the count of attributes using xpath in java without dom parser在没有dom解析器的java中使用xpath获取属性计数
【发布时间】:2021-10-13 15:46:23
【问题描述】:

我想在 java 中使用 xpath 获取属性的计数。我知道我们可以使用 DOM 解析器,但我的输入文件会非常大。我不能真正使用 SAX,因为我需要处理多个嵌套标签。我也不确定 xml 文档中的所有属性。拥有 xpath 会让我的生活更轻松,但我真的很担心 dom 解析器会阻塞内存。我阅读了有关 s9 api 的信息,但并没有真正解决它。 JAVA 中是否还有其他替代库使用没有 DOM 解析器的 xpath?分享例子真的很有帮助

假设我的输入是

<?xml version="1.0" encoding="UTF-8"?>

<cricketers>
    <continent>
        <team>
            <aussies>
                <cricketer type="righty">
                    <name>Smith</name>
                    <role>Captain</role>
                    <position>Wicket-Keeper</position>
                </cricketer>
                <cricketer type="lefty">
                <name>Warner</name>
                <role>Batsman</role>
                <position>Point</position>
                </cricketer>
            </aussies>

        </team>
    </continent>

    <continent>
        <team>
            <england>
                <cricketer type="righty">
                    <name>Morgan</name>
                    <role>Captain</role>
                    <position>Covers</position>
                </cricketer>
                <cricketer type="lefty">
                <name>Cook</name>
                <role>Batsman</role>
                <position>Point</position>
                </cricketer>
            </england>

        </team>
    </continent>

  <continent>
        <team>
            <aussies>
                <cricketer type="righty">
                    <name>Smith</name>
                    <role>Captain</role>
                    <position>Wicket-Keeper</position>
                </cricketer>
                <cricketer type="lefty">
                <name>Warner</name>
                <role>Batsman</role>
                <position>Point</position>
                </cricketer>
            </aussies>

        </team>
    </continent>
</cricketers>

给定一个 xpath //team/aussies/cricketer,在这种情况下计数是 4。 我想在没有 DOM 解析器的情况下实现这样的东西

【问题讨论】:

  • 在 XSLT 3 中使用 Saxon 10 或 9.9 EE 进行流式传输可能能够做到这一点,但它需要许可证。我不太清楚为什么 SAX 不够,您只想计算所有属性,您可能想多解释一下您有什么样的输入以及要计算哪些属性。
  • 还有像 BaseX 这样的 XML 数据库,它应该允许您首先将一个巨大的文档集成到一个数据库中,然后再对其进行查询,而不必遇到纯内存 XPath 的性能问题。跨度>
  • 您真的只想计算文档中的属性总数吗?使用 SAX 很容易做到这一点。或者你想要一些更复杂的统计数据?如果是这样,请准确说明是什么。
  • 考虑编辑您的问题并首先显示您想要处理的 XML 的代表性示例,然后是您想要使用 XPath 创建的结果的描述和示例。在 XSLT 3 中,一些路径可以通过流式传输进行流式传输,而其他路径则不是。通过流媒体通常可以计算“属性”,但我不确定您对“属性”的定义是否意味着元素节点的“属性”。
  • 通常,对于 XSLT 3 和流,使用累加器是“计数”某些节点的强大工具。

标签: java xml xpath sax s9api


【解决方案1】:

借助支持流式传输的 XSLT 3(例如,使用 Saxon EE 10 或 9.9),您可以使用

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  expand-text="yes">

  <xsl:output method="adaptive"/>
  
  <xsl:mode streamable="yes"/>

  <xsl:template match="/">
    <xsl:sequence select="count(//@*)"/>
  </xsl:template>

</xsl:stylesheet>

如果任务真的只计算所有属性。 Saxon 应该在单个文件中运行它,只转发解析整个文档,而不构建所有节点的完整树。

在没有谓词的情况下计算元素选择,例如

<xsl:template match="/">
    <xsl:sequence select="count(//team/aussies/cricketer)"/>
</xsl:template>

应该也可以。

在 s9api 中,您只需确保将输入文档作为流传递给 Xslt30Transformer,例如

    Processor processor = new Processor(true);

    XsltCompiler compiler = processor.newXsltCompiler();

    XsltExecutable executable = compiler.compile(new StreamSource("count-example1.xsl"));

    Xslt30Transformer transformer = executable.load30();

    XdmValue result = transformer.applyTemplates(new StreamSource("sample1.xml"));

    System.out.println(result);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2012-04-14
    • 2019-02-18
    • 2015-06-16
    • 2017-11-12
    • 2013-01-14
    • 1970-01-01
    相关资源
    最近更新 更多