XSLT 3.0 突发流 - 如何存储/获取另一个分支的值

问题描述 投票:0回答:1

我们使用 Saxon EE 12.x 将大型(多 GB)XML 文件转换为更小的内部 XML 结构。 我们希望减少每个

<Document>
节点上的内存消耗和突发流,这似乎与我们的应用程序完美匹配。它有效 - 但我们在一些看似简单的构造上遇到了困难:如何获取
<PrintDate>
分支的
<ExportHeader>
等信息并将其作为流模式下的属性添加到每个输出
<Doc>
元素?

源XML包含1000个

<Document>
节点,每个
<Document>
节点包含1000行XML,
<ExportHeader>
节点非常小,只包含一些元信息。简化的源 XML 示例如下所示:

<Export>
  <ExportHeader>
    <PrintDate>2024-12-24</PrintDate>
  </ExportHeader>
  <ExportContent>
    <Document>
      <LotsOfXml></LotsOfXml>
    </Document>
    <Document>
      <LotsOfXml></LotsOfXml>
    </Document>
    <Document>
      <LotsOfXml></LotsOfXml>
    </Document>
  </ExportContent>
</Export>

我们的目标 XML 应如下所示:

<Exp>
  <Doc PrintDate="???">
    <LotsOfTransformedXML></LotsOfTransformedXML>
  </Doc>
  <Doc PrintDate="???">
    <LotsOfTransformedXML></LotsOfTransformedXML>
  </Doc>
  <Doc PrintDate="???">
    <LotsOfTransformedXML></LotsOfTransformedXML>
  </Doc>
</Exp>

一个非常简单的 XSLT 看起来像这样,但我们不知道如何在不破坏可流性的情况下将

<PrintDate>
放入
<Doc>
节点属性中...可以使用
<xsl:accumulator>
来存储/获取值,如果是,如何?

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:math="http://www.w3.org/2005/xpath-functions/math"
  exclude-result-prefixes="xs math"
  version="3.0">
  
  <xsl:mode streamable="yes" on-no-match="shallow-skip"/>
  <xsl:mode name="insideDoc" streamable="no" on-no-match="shallow-copy "/>
  
  <xsl:template match="Export">
    <xsl:element name="Exp">
      <xsl:apply-templates></xsl:apply-templates>
    </xsl:element>
  </xsl:template>
  
    <xsl:template match="PrintDate">
      <!-- how to keep/store this PrintDate, so we can add it to the Doc elements as an attribute later... -->
    </xsl:template>

  <xsl:template match="ExportContent">
    <xsl:apply-templates select="copy-of(Document)" mode="insideDoc"/>
  </xsl:template>
  
  <xsl:template match="Document" mode="insideDoc">
    <xsl:element name="Doc">
      <xsl:attribute name="PrintDate" select="'???'"/>
      <xsl:apply-templates select="*" mode="insideDoc"/>      
    </xsl:element>
  </xsl:template>
  
  <xsl:template match="LotsOfXml" mode="insideDoc">
    <xsl:element name="LotsOfTransformedXML">
    </xsl:element>
  </xsl:template>
  
</xsl:stylesheet>
xml xslt streaming saxon xslt-3.0
1个回答
0
投票

使用捕获累加器https://www.saxonica.com/html/documentation12/extensions/attributes/capture.html例如

<xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="PrintDate"/>

<xsl:accumulator name="PrintDate" as="element(PrintDate)*" initial-value="()" streamable="yes">
  <xsl:accumulator-rule saxon:capture="yes" match="ExportHeader/PrintDate"
    phase="end" select="$value, ."/>
</xsl:accumulator>

...

<xsl:attribute name="PrintDate" select="accumulator-before('PrintDate')"/>
© www.soinside.com 2019 - 2024. All rights reserved.