使用 XPaths 和 elementpath 库查找节点的第一次出现而不遍历所有节点

Find first occurence of node without traversing all of them using XPaths and elementpath library

我使用 elementpath 来处理一些 XPath 查询。我有一个具有线性结构的 XML,其中包含一个独特的 id 属性。

<items>
  <item id="1">...</item>
  <item id="2">...</item>
  <item id="3">...</item>
  ... 500k elements
  <item id="500003">...</item>
</items>

我希望解析器在不遍历所有节点的情况下找到第一个出现的地方。例如,我想 select //items/item[@id = '3'] 并在仅迭代 3 个节点(不超过 500k 个节点)后停止。对于许多情况来说,这将是一个很好的优化。

使用带有 XPath 静态参数的 XSLT 3 流式传输的示例,然后使用 xsl:iteratexsl:break 在找到第一个项目后生成“提前退出”将是

<?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">
  
  <xsl:param name="path" static="yes" as="xs:string" select="'items/item[@id = ''3'']'"/>

  <xsl:output method="xml"/>

  <xsl:mode on-no-match="shallow-copy" streamable="yes"/>

  <xsl:template match="/" name="xsl:initial-template">
    <xsl:iterate _select="{$path}">
      <xsl:if test="position() = 1">
        <xsl:copy-of select="."/>
        <xsl:break/>
      </xsl:if>
    </xsl:iterate>
  </xsl:template>

</xsl:stylesheet>

您可以 运行 使用 SaxonC EE(不幸的是只有 EE 支持流式传输)和 Python 例如

import saxonc

with saxonc.PySaxonProcessor(license=True) as proc:
    print("Test SaxonC on Python")
    print(proc.version)
    
    xslt30proc = proc.new_xslt30_processor()

    xslt30proc.set_parameter('path', proc.make_string_value('/items/item[@id = "2"]'))

    transformer = xslt30proc.compile_stylesheet(stylesheet_file='iterate-items-early-exit1.xsl')
    
    xdm_result = transformer.apply_templates_returning_value(source_file='items-sample1.xml')

    if transformer.exception_occurred:
        print(transformer.error_message)

    print(xdm_result)