使用 XSLT 3.0 跳过第一个节点并复制其余节点

Skip first node and Copy rest of the nodes using XSLT 3.0

我需要跳过第一个 Worker 节点并使用 XSLT 3.0 复制其余节点

我的来源XML是

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
    <Worker>
        <Employee>Emp</Employee>
        <ID>Identifier</ID>
    </Worker>
    <Worker>
        <Employee>12344</Employee>
        <ID>1245599</ID>
    </Worker>
    <Worker>
        <Employee>25644</Employee>
        <ID>7823565</ID>
    </Worker>
</Workers>

并且期望的输出是

<?xml version="1.0" encoding="utf-8"?>
<Workers>
   <Worker>
      <Employee>12344</Employee>
      <ID>1245599</ID>
   </Worker>
   <Worker>
      <Employee>25644</Employee>
      <ID>7823565</ID>
   </Worker>
</Workers>

我拥有的 XSLT 是

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:strip-space elements="*"/>
    <xsl:output method="xml" indent="yes"/>


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

    <xsl:template match="Worker[position() = 1]"/>

</xsl:stylesheet>

上面的 XSLT 产生了我期望的输出,但我想看看是否有更好的方法来跳过第一个节点而不使用 postion(),因为我不确定我当前代码的效率如何是处理大文件(大约 800 MB)

我不得不使用以下方法从我的结果中删除空格 XML

<xsl:strip-space elements="*"/>

任何人都可以检查我的代码并提供任何改进我的代码的建议吗?

===============

根据 Michael Kay 的建议,我的代码如下所示

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"  xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:strip-space elements="*"/>
   <xsl:output method="xml" indent="yes"/> 
    
  <!-- <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template> -->
 
 <!-- Removed above Identity Transformation -->

    <xsl:mode streamable="yes" on-no-match="shallow-copy"/>
    
    <xsl:template match="Workers">
        <xsl:copy>
            <xsl:apply-templates select="tail(Worker)"/>
        </xsl:copy>
    </xsl:template>    
    
</xsl:stylesheet>

我会写的

<xsl:template match="Worker[1]"/>

为了可读性,但都是一样的。

带有位置谓词的匹配模式可能表现不佳,因此您要谨慎是对的,但像这样的简单模式应该没问题。事实上,主要的不利后果可能是 Saxon 将在 TinyTree 中分配 preceding-sibling 指针,以便它可以计算节点的兄弟位置。

Saxon 有效地将其实现为

<xsl:template match="Worker[not(preceding-sibling::Worker)]"/>

你可能更喜欢这样写。但是,这两种形式都不可流式传输。

要使其可流式传输,您可以通过不选择不需要的节点来删除它们:

<xsl:template match="Workers">
  <xsl:copy>
    <xsl:apply-templates select="tail(Worker)"/>
  </xsl:copy>
</xsl:template>

在 non-streaming 的情况下也可能稍微快一些;它节省了内存,因为 preceding-sibling 不需要指针。