在n个元素后将一个输出文件拆分为多个xml

Split one out-file into multiple xmls after n elements

我正在使用第 3 方软件生成 XML 文件。该软件允许使用 XSLT (2.0) 形式的 post 处理器。

我的输出文件比较大,经常达到几百MB,几百万行。我想分块我的输出文件并在每个文件之后有 1 个文件(比如说 10 个产品)而不是一个文件中的所有文件。

我在这里找到了一个 smiliar 线程:Split one XML file to multiple XML File with XSLT 但由于我是 XSLT 的新手,我无法弄清楚如何给出文件将被拆分的特定范围。我假设给定示例中的 xsl:for-each select="document/file"> 是要查找的表达式,但我也不确定。

一个简单的XML看起来有点像这样:

<Products>
  <Product ID="123" UserType="ITEM">
    <Name>First Product</Name>
    <Values>
      <Value AttributeID="someAttribute">foo</Value>
      <Value AttributeID="AnotherAttribute">bar</Value>
    </Values>
  </Product>
  <Product ID="456" UserType="ITEM">
    <Name>Second Product</Name>
    <Values>
      <Value AttributeID="someAttribute">foo</Value>
      <Value AttributeID="AnotherAttribute">bar</Value>
    </Values>
  </Product>
</Products>

如上所述,有数千种产品,为了清晰的概述,我省略了 <Products>-节点前后的节点。

如何将我的一个给定输出文件拆分为 N 个文件,假设在 10 个产品之后拆分这些文件?

假设 Products 元素是您可以使用的根元素的子元素,例如

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

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/*">
    <xsl:for-each-group select="*" group-adjacent="boolean(self::Products)">
      <xsl:choose>
        <xsl:when test="not(current-grouping-key()) and position() = 1">
          <xsl:result-document href="headers.xml">
            <Root>
              <xsl:copy-of select="current-group()"/>
            </Root>
          </xsl:result-document>
        </xsl:when>
        <xsl:when test="current-grouping-key()">
          <xsl:for-each-group select="current-group()/Product" group-by="(position() - 1) idiv $size">
            <xsl:result-document href="chunk-{position()}.xml">
              <Products>
                <xsl:copy-of select="current-group()"/>
              </Products>
            </xsl:result-document>
          </xsl:for-each-group>
        </xsl:when>
        <xsl:when test="not(current-grouping-key()) and position() = last()">
          <xsl:result-document href="footers.xml">
            <Root>
              <xsl:copy-of select="current-group()"/>
            </Root>
          </xsl:result-document>
        </xsl:when>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>