【问题标题】:XSLT - Split large XML into multiple files based on criteriaXSLT - 根据标准将大型 XML 拆分为多个文件
【发布时间】:2020-08-26 19:56:45
【问题描述】:

我是一名 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>

预期输出:

文件1.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 个),我玩了一下,但无法将具有单一爱好的玩家分组到单个文件中,而对于多个爱好则更糟。

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

【问题讨论】:

  • 您遇到了什么样的错误? XSLT 1 还是 XSLT 2?您使用的是什么 xslt 引擎/技术堆栈?
  • 为什么不发布您的尝试以便我们修复它,而不必从头开始为您编写代码。
  • 所以第一个输出文件包含所有players,只有一个hobby 子元素。第二个,我想,所有players 和不止一个hobby。但是,不清楚为什么 playerid1 在第二个输出中出现了 3 次。如果您希望每个hobby 都有一个player 结果,player 1 不应该出现五次吗?
  • 对不起,我会在这里发布所有试验并恢复​​。
  • Bknights ,抱歉回答迟了。使用 XSLT,不太确定您对引擎/技术堆栈的含义,只是使用氧气来运行它,不熟悉这些。 michael.hor257k,我用我一直在做的试验重新更新了线程。 @MartinHonnen,我已经正确地重新更新了它,错误的示例复制和粘贴。如果您需要更多信息,请告诉我,谢谢

标签: xml xslt xslt-2.0 xslt-grouping


【解决方案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>

【讨论】:

  • 这行得通,非常感谢,但在我盲目使用它之前,我需要自己了解所有内容。非常感谢!
  • “我需要自己理解一切” 我强烈建议您这样做。如果您需要任何说明,请询问。
猜你喜欢
  • 1970-01-01
  • 2019-06-14
  • 2022-01-16
  • 2023-03-17
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多