XSLT转换:将文件分组并拆分为

时间:2017-09-10 07:53:39

标签: xml xslt-2.0 saxon

我是XSLT转换的新手,拥有非常基础的知识。 我在寻求你的帮助。我有一个XML文件,请参阅下面的示例。我想将此文件拆分为多个较小的文件。

我想根据cmfp:future和cmfp:quotation的值进行分组。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GuiRoot xmlns:cmfp="mx.MarketParameters.Fixing.Commodities.Futures" xmlns:mp="mx.MarketParameters" xmlns:fg="mx.MarketParameters.Fixing" xmlns:fgrt="mx.MarketParameters.Fixing.IRIndices" xmlns:xc="xmlCache" xmlns:fgfx="mx.MarketParameters.Fixing.FXIndices" xmlns:cmip="mx.MarketParameters.Commodities.Indices">
 <xc:XmlCache xc:action="Update">
  <xc:XmlCacheArea xc:value="MarketParameters">
   <mp:nickName xc:subset="Reference" xc:value="./BORATES">
    <mp:date xc:value="20161202">
     <fg:fixing>
      <cmfp:futurePrice>
       <cmfp:future xc:value="ONE">
        <cmfp:quotation xc:value="1.1">
         <cmfp:maturity xc:value="1.1.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
       <cmfp:future xc:value="ONE">
        <cmfp:quotation xc:value="1.2">
         <cmfp:maturity xc:value="1.2.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
        <cmfp:quotation xc:value="1.2">
         <cmfp:maturity xc:value="1.2.2">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13406.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
       <cmfp:future xc:value="TWO">
        <cmfp:quotation xc:value="2.1">
         <cmfp:maturity xc:value="2.1.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
       <cmfp:future xc:value="THREE">
        <cmfp:quotation xc:value="3.1">
         <cmfp:maturity xc:value="3.1.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
       <cmfp:future xc:value="FOUR">
        <cmfp:quotation xc:value="4.1">
         <cmfp:maturity xc:value="4.1.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
       <cmfp:future xc:value="EIGHT">
        <cmfp:quotation xc:value="8.1">
         <cmfp:maturity xc:value="8.1.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
      </cmfp:futurePrice>
     </fg:fixing>
    </mp:date>
   </mp:nickName>
  </xc:XmlCacheArea>
 </xc:XmlCache>
</GuiRoot>

期望的输出 File1

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GuiRoot xmlns:cmfp="mx.MarketParameters.Fixing.Commodities.Futures" xmlns:mp="mx.MarketParameters" xmlns:fg="mx.MarketParameters.Fixing" xmlns:fgrt="mx.MarketParameters.Fixing.IRIndices" xmlns:xc="xmlCache" xmlns:fgfx="mx.MarketParameters.Fixing.FXIndices" xmlns:cmip="mx.MarketParameters.Commodities.Indices">
 <xc:XmlCache xc:action="Update">
  <xc:XmlCacheArea xc:value="MarketParameters">
   <mp:nickName xc:subset="Reference" xc:value="./BORATES">
    <mp:date xc:value="20161202">
     <fg:fixing>
      <cmfp:futurePrice>
       <cmfp:future xc:value="ONE">
        <cmfp:quotation xc:value="1.1">
         <cmfp:maturity xc:value="1.1.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
        <cmfp:quotation xc:value="1.2">
         <cmfp:maturity xc:value="1.2.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
         <cmfp:maturity xc:value="1.2.2">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13406.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
       <cmfp:future xc:value="FOUR">
        <cmfp:quotation xc:value="4.1">
         <cmfp:maturity xc:value="4.1.1">
          <cmfp:column xc:value="CLOSE" xc:type="Fields">
           <mp:HisValue xc:keyFormat="C">[startDate="19990101"][endDate="19990101"]13405.00</mp:HisValue>
          </cmfp:column>
         </cmfp:maturity>
        </cmfp:quotation>
       </cmfp:future>
      </cmfp:futurePrice>
     </fg:fixing>
    </mp:date>
   </mp:nickName>
  </xc:XmlCacheArea>
 </xc:XmlCache>
</GuiRoot>

文件2 simlar to file 1但是基于mod结果的不同节点......

文件3 simlar to file 1但是基于mod结果的不同节点......

请提供帮助......提前致谢

  

我尝试使用下面的XSLT代码,但它没有给我所需的输出....

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cmfp="mx.MarketParameters.Fixing.Commodities.Futures" xmlns:mp="mx.MarketParameters" xmlns:fg="mx.MarketParameters.Fixing" xmlns:fgrt="mx.MarketParameters.Fixing.IRIndices" xmlns:xc="xmlCache" xmlns:fgfx="mx.MarketParameters.Fixing.FXIndices" xmlns:cmip="mx.MarketParameters.Commodities.Indices" exclude-result-prefixes="cmfp mp fg fgrt xc fgfx cmip">
 <xsl:output method="xml" version="1.0" omit-xml-declaration="no" standalone="yes" encoding="UTF-8" indent="yes"/>
 <!-- define variables  [start] -->
 <xsl:variable name="action" select="/GuiRoot/xc:XmlCache/@xc:action"/>
 <xsl:variable name="nickname" select="/GuiRoot/xc:XmlCache/xc:XmlCacheArea/mp:nickName/@xc:value"/>
 <xsl:variable name="mpdate" select="/GuiRoot/xc:XmlCache/xc:XmlCacheArea/mp:nickName/mp:date/@xc:value"/>
 <xsl:variable name="noOfSplits" select="3"/>
 <!-- define variables  [ end  ]-->
 <xsl:template match="cmfp:futurePrice">
  <xsl:apply-templates select="cmfp:futurePrice"/>
  <xsl:for-each-group select="cmfp:future" group-by="(position() -1) mod $noOfSplits">
   <xsl:variable name="file_name" select="format-number(current-grouping-key(),'000')"/>
   <xsl:result-document href="files/cmfp_SPLIT_{$file_name}.xml">
    <GuiRoot xmlns:cmfp="mx.MarketParameters.Fixing.Commodities.Futures" xmlns:mp="mx.MarketParameters" xmlns:fg="mx.MarketParameters.Fixing" xmlns:fgrt="mx.MarketParameters.Fixing.IRIndices" xmlns:xc="xmlCache" xmlns:fgfx="mx.MarketParameters.Fixing.FXIndices" xmlns:cmip="mx.MarketParameters.Commodities.Indices">
     <xc:XmlCache>
      <xsl:attribute name="xc:action">
       <xsl:value-of select="$action"/>
      </xsl:attribute>
      <xc:XmlCacheArea xc:value="MarketParameters">
       <mp:nickName xc:subset="Reference">
        <xsl:attribute name="xc:value">
         <xsl:value-of select="$nickname"/>
        </xsl:attribute>
        <mp:date>
         <xsl:attribute name="xc:value">
          <xsl:value-of select="$mpdate"/>
         </xsl:attribute>
         <fg:fixing>
          <cmfp:futurePrice>
           <xsl:copy-of select="current-group()"/>
          </cmfp:futurePrice>
         </fg:fixing>
        </mp:date>
       </mp:nickName>
      </xc:XmlCacheArea>
     </xc:XmlCache>
    </GuiRoot>
   </xsl:result-document>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

我认为您首先需要分组,然后您可以根据位置进行拆分,以下是使用XSLT 3.0(由Saxon 9.8(所有版本)或9.7 PE和EE支持)的尝试:

<?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"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xpath-default-namespace="mx.MarketParameters.Fixing.Commodities.Futures"
    xmlns:xc="xmlCache"
    exclude-result-prefixes="xs math"
    version="3.0">

    <xsl:output indent="yes"/>

    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="noOfSplits" select="3"/>

    <xsl:template match="/">
        <xsl:variable name="original-root-element" select="*"/>
        <xsl:variable name="groups">
            <xsl:for-each-group select="//future" group-by="@xc:value">
                <xsl:copy>
                    <xsl:copy-of select="@*"/>
                    <xsl:for-each-group select="current-group()/quotation" group-by="@xc:value">
                        <xsl:copy>
                            <xsl:copy-of select="@*, current-group()/node()"/>
                        </xsl:copy>
                    </xsl:for-each-group>
                </xsl:copy>
            </xsl:for-each-group>
        </xsl:variable>
        <xsl:for-each-group select="$groups/future" group-by="(position() - 1) mod $noOfSplits">
          <xsl:result-document href="split{position()}.xml">
            <xsl:apply-templates select="$original-root-element">
                <xsl:with-param name="contents" select="current-group()" tunnel="yes"/>
            </xsl:apply-templates>
          </xsl:result-document>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="futurePrice">
        <xsl:param name="contents" tunnel="yes"/>
        <xsl:copy>
            <xsl:copy-of select="$contents"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

要使用旧的Saxon 9版本的XSLT 2.0处理器运行它,你必须拼写出身份转换浅拷贝,例如。

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

而不是使用xsl:mode