XSLT - 根据条件将大型 XML 拆分为多个文件

XSLT - Split large XML into multiple files based on criteria

我是一名 XSLT 2.0 初学者,正在尝试找到一种根据条件将大 xml 文件拆分为多个块的方法。

样本XML:

<?xml version="1.0" encoding="UTF-8"?>
<players>
    <player>
        <id>1</id>
        <fname>Vcut</fname>
        <lname>Piatos</lname>
        <age>0</age>
        <code>1002</code> 
        <hobby>reading</hobby>
        <hobby>sports</hobby>
        <hobby>travelling</hobby>
    </player>
    <player>
        <id>2</id>
        <fname>Mayo</fname>
        <lname>Naise</lname>
        <age>22</age>
        <code>1003</code>
        <hobby>reading books</hobby>
        <hobby>program hobyist</hobby>
        <hobby>watching tutorials</hobby>
    </player>
    <player>
        <id>3</id>
        <fname>Ben</fname>
        <lname>Ten</lname>
        <age>22</age>
        <code>1004</code>
        <hobby>play sports</hobby>
    </player>
    <player>
        <id>4</id>
        <fname>Dummy</fname>
        <lname>One</lname>
        <age>22</age>
        <code>1005</code>
        <hobby>Eat</hobby>
    </player>
    <player>
        <id>5</id>
        <fname>Dummy</fname>
        <lname>Two</lname>
        <age>23</age>
        <code>1006</code>
        <hobby>sleep</hobby>
    </player>
</players>

预期输出:

File1.xml

<players>
  <player>
      <id>3</id>
      <fname>Ben</fname>
      <lname>Ten</lname>
      <age>22</age>
      <code>1004</code>
      <hobby>play sports</hobby>
  </player>
  <player>
      <id>4</id>
      <fname>Dummy</fname>
      <lname>One</lname>
      <age>22</age>
      <code>1005</code>
      <hobby>Eat</hobby>
  </player>
  <player>
      <id>5</id>
      <fname>Dummy</fname>
      <lname>Two</lname>
      <age>23</age>
      <code>1006</code>
      <hobby>sleep</hobby>
  </player>
</players>

file2.xml 多种爱好

<?xml version="1.0" encoding="UTF-8"?>
<players>
  <player>
      <id>1</id>
      <fname>Vcut</fname>
      <lname>Piatos</lname>
      <age>0</age>
      <code>1002</code>
      <hobby>reading</hobby>
  </player>
  <player>
      <id>1</id>
      <fname>Vcut</fname>
      <lname>Piatos</lname>
      <age>0</age>
      <code>1002</code>
      <hobby>sports</hobby>
  </player>
  <player>
      <id>1</id>
      <fname>Vcut</fname>
      <lname>Piatos</lname>
      <age>0</age>
      <code>1002</code>
      <hobby>travelling</hobby>
  </player>
  <player>
      <id>2</id>
      <fname>Mayo</fname>
      <lname>Naise</lname>
      <age>22</age>
      <code>1003</code>
      <hobby>reading books</hobby>        
  </player>
      <player>
      <id>2</id>
      <fname>Mayo</fname>
      <lname>Naise</lname>
      <age>22</age>
      <code>1003</code>       
      <hobby>program hobyist</hobby>      
  </player>
      <player>
      <id>2</id>
      <fname>Mayo</fname>
      <lname>Naise</lname>
      <age>22</age>
      <code>1003</code>       
      <hobby>watching tutorials</hobby>
  </player>
</players>

尝试应用提供的相同解决方案 here,但未能成功。

你有什么建议吗?我的想法是计算每个玩家的爱好,但不确定如何拆分它并在之后复制其他部分..

<xsl:if count(player/hobby> > 1 )

我实际使用的 XSLT(实际上是我共享的引用解决方案的副本)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    
    <xsl:output indent="yes"/>
   
    <xsl:template match="/">
        <xsl:apply-templates select="*/player"/>
    </xsl:template>
    
    <xsl:template match="*/player">
        <xsl:result-document href="Output{position()}.xml">
            <xsl:apply-templates select="/*" mode="split">
                <xsl:with-param name="target" tunnel="yes" select="current()"/>
            </xsl:apply-templates>
        </xsl:result-document>
    </xsl:template>
    
    <xsl:template match="@* | node()" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="@*, node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="*/player" mode="split">
        <xsl:param name="target" tunnel="yes"/>
        <xsl:if test="$target is .">
            <xsl:next-match/>
        </xsl:if>
    </xsl:template>
    
    
</xsl:stylesheet>

这会产生 5 个文件(每个玩家 1 个),我玩了一会儿,但无法将具有单一爱好的玩家分组到单个文件中,而对于多个爱好,情况更糟。

如果您能分享更多方向,将不胜感激。

AFAICT,你可以简单地做:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/players">
    <xsl:for-each-group select="player" group-by="count(hobby) gt 1 ">
        <result-document href="Output{position()}.xml">
            <players>
                <xsl:apply-templates select="current-group()/hobby"/>
            </players>
        </result-document>
    </xsl:for-each-group>
</xsl:template>

<xsl:template match="hobby">
    <player>
        <xsl:copy-of select="../* except ../hobby, ."/>
    </player>
</xsl:template>
 
</xsl:stylesheet>