根据属性值分割XML文件

时间:2019-12-29 12:04:21

标签: xml xslt xslt-1.0 xslt-2.0

需要根据属性值分割XML文件。是否可以使用XSLT-1.0?如果没有可能用1.0版本做到这一点,我将不胜感激任何更高版本的XSLT代码。

这里是数字拆分属性的值(10、11、12等)。但是我想解决方案的原理对于数字和非数字序列可能是通用的。系统找到第一个新的(更改的)拆分属性值后,便会生成新文件。

(可选问题)。这些操作可能有多少个XML文件?是否可以处理3gb文件? 30GB文件? RAM是否有系统要求来处理此类文件大小?

来源:

<objects>
  <obj attribute-1="value" attribute-2="value2" split-attribute="10"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="10"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="10"/>

  <obj attribute-1="value" attribute-2="value2" split-attribute="11"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="11"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="11"/>

  <obj attribute-1="value" attribute-2="value2" split-attribute="12"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="12"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="12"/>
</objects>

期望的输出

<objects>
  <obj attribute-1="value" attribute-2="value2" split-attribute="10"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="10"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="10"/>
</objects>
<!--=========================== file-1.xml ======================-->


<objects>
  <obj attribute-1="value" attribute-2="value2" split-attribute="11"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="11"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="11"/>
</objects>
<!--=========================== file-2.xml ======================-->

<objects>
  <obj attribute-1="value" attribute-2="value2" split-attribute="12"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="12"/>
  <obj attribute-1="value" attribute-2="value2" split-attribute="12"/>
</objects>
<!--=========================== file-3.xml ======================-->

2 个答案:

答案 0 :(得分:2)

这可以使用XSLT-2.0及更高版本来完成。所需的xsl:result-document函数是在2.0版中引入的。

现在解决方案很简单:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/objects">
    <xsl:for-each-group select="obj" group-by="@split-attribute">
      <xsl:result-document href="{concat('File-',position(),'.xml')}" indent="yes">
        <objects>
          <xsl:copy-of select="current-group()" />
        </objects>
      </xsl:result-document>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

输出是所需的,并且包含三个单独的文件。

答案 1 :(得分:0)

您有一个不错的XSLT 2.0答案,尽管我认为使用group-adjacent仍然可以满足您的需要(“当系统找到split-attribute的第一个新(更改)值时,将生成新文件”);要使其与XSLT 3和流技术(以及支持该技术的处理器,如Saxon 9 EE)一起使用,您可以使用

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:mode stremable="yes"/>

  <xsl:template match="/objects">
    <xsl:for-each-group select="obj" group-adjacent="@split-attribute">
      <xsl:result-document href="file-{position()}.xml" indent="yes">
        <objects>
          <xsl:copy-of select="current-group()" />
        </objects>
      </xsl:result-document>
    </xsl:for-each-group>
  </xsl:template>

</xsl:stylesheet>

这样,它甚至应该可以处理非常大的文件。