对已分组的记录进行分组,并使用XSL1.0从组头填充信息



我正在尝试将会计系统的XML输出转换为可以导入Access的XML。不幸的是,Access只接受XSL1.0进行转换,所以我已经请求帮助将XSL2.0解决方案转换为在XSL1.0下工作的解决方案。(分组问题)。那里的解决方案非常适合我认为Access导入所需的内容。

Access导入现在可以工作了,但我意识到数据的形式仍然不可用。数据由标题行和子行组成,这些行不填充标题数据。但要进行有意义的汇总,数据需要填写。

这就是当前导入Access的XML的样子:

DBCDATE     |DBBCPARTY         |DBCVCHTYPE     |DBCVCHNO   |DBCVCHREF    
1-Apr-2011  |                  |Stock Journal  |1          |             
            |ME KN YARN B      |               |           |             
            |ME KN YARN G      |               |           |             
            |ME KN YARN I      |               |           |             
3-Apr-2011  |                  |Stock Journal  |2          |903          
            |TIB Raw Wool      |               |           |             
            |ME KN YARN D      |               |           |             

头行中的字段也需要向下复制到子行中:DBCDATE、DBCVCHTYPE、DBCVCHNO、DBCVCHREF、DBCNARR

我可以在Access中使用一些VBA编程,甚至可以将数据导出到Excel中并应用一些公式,但数据相当大,我们正在考虑提取更多数据。而且它的灵活性会降低。此外,这个问题可能会进一步将已经分组的XML分组(现在它以InventoryDaybook标记结构的形式分组为可导入行)

所以这就是最初的XML:编辑:增强的XML片段以更好地测试

<ENVELOPE>
  <DBCFIXED>  <DBCDATE>1-Apr-2011</DBCDATE>
    <DBCPARTY></DBCPARTY>
  </DBCFIXED>
  <DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
  <DBCVCHNO>1</DBCVCHNO>
  <DBCVCHREF></DBCVCHREF>
  <DBCSTNO></DBCSTNO>
  <DBCSERVICETAXNO></DBCSERVICETAXNO>
  <DBCPANNO></DBCPANNO>
  <DBCCSTNO></DBCCSTNO>
  <DBCNARR>Opening balance transfar</DBCNARR>
  <DBCQTY>0.000 Kg</DBCQTY>
  <DBCRATE></DBCRATE>
  <DBCAMOUNT></DBCAMOUNT>
  <DBCADDLCOST></DBCADDLCOST>
  <DBCGROSSAMT></DBCGROSSAMT>
  <DBCLEDAMT></DBCLEDAMT>
  <DBCFIXED>  <DBCDATE></DBCDATE>
    <DBCPARTY>ME KN YARN BL 1</DBCPARTY>
  </DBCFIXED>
  <DBCVCHTYPE></DBCVCHTYPE>
  <DBCVCHNO></DBCVCHNO>
  <DBCVCHREF></DBCVCHREF>
  <DBCSTNO></DBCSTNO>
  <DBCSERVICETAXNO></DBCSERVICETAXNO>
  <DBCPANNO></DBCPANNO>
  <DBCCSTNO></DBCCSTNO>
  <DBCNARR></DBCNARR>
  <DBCQTY>0.150 Kg</DBCQTY>
  <DBCRATE>566.00/Kg</DBCRATE>
  <DBCAMOUNT>-84.90</DBCAMOUNT>
  <DBCADDLCOST></DBCADDLCOST>
  <DBCGROSSAMT></DBCGROSSAMT>
  <DBCLEDAMT></DBCLEDAMT>
  <DBCFIXED>  <DBCDATE>1-Apr-2011</DBCDATE>
    <DBCPARTY></DBCPARTY>
  </DBCFIXED>
  <DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
  <DBCVCHNO>2</DBCVCHNO>
  <DBCVCHREF>903</DBCVCHREF>
  <DBCSTNO></DBCSTNO>
  <DBCSERVICETAXNO></DBCSERVICETAXNO>
  <DBCPANNO></DBCPANNO>
  <DBCCSTNO></DBCCSTNO>
  <DBCNARR>Opening balance transfar</DBCNARR>
  <DBCQTY>0.000 Kg</DBCQTY>
  <DBCRATE></DBCRATE>
  <DBCAMOUNT></DBCAMOUNT>
  <DBCADDLCOST></DBCADDLCOST>
  <DBCGROSSAMT></DBCGROSSAMT>
  <DBCLEDAMT></DBCLEDAMT>
  <DBCFIXED>  <DBCDATE></DBCDATE>
    <DBCPARTY>ME KN YARN BL 1</DBCPARTY>
  </DBCFIXED>
  <DBCVCHTYPE></DBCVCHTYPE>
  <DBCVCHNO></DBCVCHNO>
  <DBCVCHREF></DBCVCHREF>
  <DBCSTNO></DBCSTNO>
  <DBCSERVICETAXNO></DBCSERVICETAXNO>
  <DBCPANNO></DBCPANNO>
  <DBCCSTNO></DBCCSTNO>
  <DBCNARR></DBCNARR>
  <DBCQTY>0.260 Kg</DBCQTY>
  <DBCRATE>26.00/Kg</DBCRATE>
  <DBCAMOUNT>-8.70</DBCAMOUNT>
  <DBCADDLCOST></DBCADDLCOST>
  <DBCGROSSAMT></DBCGROSSAMT>
  <DBCLEDAMT></DBCLEDAMT>
  <DBCFIXED>  <DBCDATE></DBCDATE>
    <DBCPARTY>ME KN YARN BL 1</DBCPARTY>
  </DBCFIXED>
  <DBCVCHTYPE></DBCVCHTYPE>
  <DBCVCHNO></DBCVCHNO>
  <DBCVCHREF></DBCVCHREF>
  <DBCSTNO></DBCSTNO>
  <DBCSERVICETAXNO></DBCSERVICETAXNO>
  <DBCPANNO></DBCPANNO>
  <DBCCSTNO></DBCCSTNO>
  <DBCNARR></DBCNARR>
  <DBCQTY>0.360 Kg</DBCQTY>
  <DBCRATE>21.00/Kg</DBCRATE>
  <DBCAMOUNT>-45.80</DBCAMOUNT>
  <DBCADDLCOST></DBCADDLCOST>
  <DBCGROSSAMT></DBCGROSSAMT>
  <DBCLEDAMT></DBCLEDAMT>
</ENVELOPE>

这是XSL(XSLT1.0),与解决方案略有不同:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
   <xsl:key name="records" match="ENVELOPE/*[not(self::DBCFIXED)]" use="generate-id(preceding-sibling::DBCFIXED[1])" />
   <xsl:template match="/ENVELOPE">
      <Data>
         <xsl:apply-templates select="DBCFIXED" />
      </Data>
   </xsl:template>
   <xsl:template match="DBCFIXED">
      <InventoryDaybook>
         <xsl:copy-of select="./*" />
         <xsl:apply-templates select="key('records', generate-id())" />
      </InventoryDaybook>
   </xsl:template>
   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

编辑:提供结果XML(感谢Martin指出丢失的结果XML)

最终的XML应该是这样的:InventoryDaybook包装标签被进一步区分为"页眉"标签,其中包含日期、凭证类型、凭证编号、凭证参考和叙述信息。这些字段DBCDATE、DBCVCHTYPE、DBCVCHNO、DBCVCHREF、DBCNARR需要复制到其他InventoryDaybook包装标记中,这些标记表示"sub"行"Headers"可以由DBCDATE标识-此字段仅针对标头行设置。

<Data>
   <InventoryDaybook name="header">
      <DBCDATE>1-Apr-2011</DBCDATE>
      <DBCPARTY/>
      <DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
      <DBCVCHNO>1</DBCVCHNO>
      <DBCVCHREF/>
      <DBCSTNO/>
      <DBCSERVICETAXNO/>
      <DBCPANNO/>
      <DBCCSTNO/>
      <DBCNARR>Opening balance transfar</DBCNARR>
      <DBCQTY>0.000 Kg</DBCQTY>
      <DBCRATE/>
      <DBCAMOUNT/>
      <DBCADDLCOST/>
      <DBCGROSSAMT/>
      <DBCLEDAMT/>
   </InventoryDaybook>
   <InventoryDaybook name="sub">
      <DBCDATE>1-Apr-2011</DBCDATE>
      <DBCPARTY>ME KN YARN BL 1</DBCPARTY>
      <DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
      <DBCVCHNO>1</DBCVCHNO>
      <DBCVCHREF/>
      <DBCSTNO/>
      <DBCSERVICETAXNO/>
      <DBCPANNO/>
      <DBCCSTNO/>
      <DBCNARR>Opening balance transfar</DBCNARR>
      <DBCQTY>0.150 Kg</DBCQTY>
      <DBCRATE>566.00/Kg</DBCRATE>
      <DBCAMOUNT>-84.90</DBCAMOUNT>
      <DBCADDLCOST/>
      <DBCGROSSAMT/>
      <DBCLEDAMT/>
   </InventoryDaybook>
   <InventoryDaybook name="header">
      <DBCDATE>1-Apr-2011</DBCDATE>
      <DBCPARTY/>
      <DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
      <DBCVCHNO>2</DBCVCHNO>
      <DBCVCHREF>903</DBCVCHREF>
      <DBCSTNO/>
      <DBCSERVICETAXNO/>
      <DBCPANNO/>
      <DBCCSTNO/>
      <DBCNARR>Opening balance transfar</DBCNARR>
      <DBCQTY>0.000 Kg</DBCQTY>
      <DBCRATE/>
      <DBCAMOUNT/>
      <DBCADDLCOST/>
      <DBCGROSSAMT/>
      <DBCLEDAMT/>
   </InventoryDaybook>
   <InventoryDaybook name="sub">
      <DBCDATE>1-Apr-2011</DBCDATE>
      <DBCPARTY>ME KN YARN BL 1</DBCPARTY>
      <DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
      <DBCVCHNO>2</DBCVCHNO>
      <DBCVCHREF>903</DBCVCHREF>
      <DBCSTNO/>
      <DBCSERVICETAXNO/>
      <DBCPANNO/>
      <DBCCSTNO/>
      <DBCNARR>Opening balance transfar</DBCNARR>
      <DBCQTY>0.260 Kg</DBCQTY>
      <DBCRATE>26.00/Kg</DBCRATE>
      <DBCAMOUNT>-8.70</DBCAMOUNT>
      <DBCADDLCOST/>
      <DBCGROSSAMT/>
      <DBCLEDAMT/>
   </InventoryDaybook>
   <InventoryDaybook name="sub">
      <DBCDATE>1-Apr-2011</DBCDATE>
      <DBCPARTY>ME KN YARN BL 1</DBCPARTY>
      <DBCVCHTYPE>Stock Journal</DBCVCHTYPE>
      <DBCVCHNO>2</DBCVCHNO>
      <DBCVCHREF>903</DBCVCHREF>
      <DBCSTNO/>
      <DBCSERVICETAXNO/>
      <DBCPANNO/>
      <DBCCSTNO/>
      <DBCNARR>Opening balance transfar</DBCNARR>
      <DBCQTY>0.360 Kg</DBCQTY>
      <DBCRATE>21.00/Kg</DBCRATE>
      <DBCAMOUNT>-45.80</DBCAMOUNT>
      <DBCADDLCOST/>
      <DBCGROSSAMT/>
      <DBCLEDAMT/>
   </InventoryDaybook>
</Data>

有没有一种方法可以在XSL中做到这一点?我还想知道这是否意味着要再次转换返回的XML?这个解决方案中有类似的内容吗?双重转换问题的解决方案

我意识到我在论坛上就同一个更大的问题问了两次,但我真的很感谢你在这方面的帮助。

您当然可以使用单页管道解决方案。这里是一个使用两个分组键的非管道解决方案。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />  
   <xsl:key name="header" match="ENVELOPE/*" use="generate-id(
  (preceding-sibling::DBCFIXED[DBCDATE != '']|self::DBCFIXED[DBCDATE != ''])[last()])" />
   <!-- The header key groups all the nodes belonging to a DBCDATE. This is
        a big group containing a number of 'sub' subgroups. -->
   <xsl:key name="sub" match="ENVELOPE/*" use="generate-id(
  (preceding-sibling::DBCFIXED|self::DBCFIXED)[last()])" />
   <!-- The sub key groups all the nodes under a DBCFIXED. This corresponds to
        one row in Access -->
   <xsl:template match="/*">
    <!-- This is our entry template. We gather up all the big header groups,
         and process them one group at a time in 'header' mode. -->  
      <Data>
         <xsl:apply-templates select="DBCFIXED[DBCDATE != '']" mode="header" />
      </Data>
   </xsl:template>
   <xsl:template match="DBCFIXED" mode="header">
    <!-- In this template we process the header group. -->
      <InventoryDaybook name="header">
         <!-- The first sub-group of the header group is to be marked as
              @name="header". Process the header subgroup -->
         <xsl:apply-templates select="key('sub', generate-id())" />
      </InventoryDaybook>
      <!-- Now process the other subgroups. These will be marked @name="sub". --> 
      <xsl:apply-templates select="
        key('header', generate-id()) /
        self::DBCFIXED[DBCDATE = '']"
        mode="sub" />
   </xsl:template>
   <xsl:template match="DBCFIXED" mode="sub">
      <!-- Processing a "sub" subgroup. -->
      <InventoryDaybook name="sub">
         <xsl:apply-templates select="key('sub', generate-id())" />
         <!-- The above selects the members of the subgroup. -->
      </InventoryDaybook>
   </xsl:template>
  <xsl:template match="ENVELOPE/*
    [not(self::DBCFIXED)]
    [preceding-sibling::DBCFIXED[1][DBCDATE = '']]
    [.='']">
  <!-- When we are processing a normal node in a 'sub' subgroup AND
       it doesn't have a value, pick up the default value from
       the related 'header' subgroup. This rule doesn't work for
       the DBCFIXED node. We need a special template for that. -->
      <xsl:copy>
        <xsl:value-of select="
        key('sub', generate-id(
        preceding-sibling::DBCFIXED[DBCDATE != ''][1]))        
        [local-name()=local-name(current())][1] " />
      </xsl:copy>
   </xsl:template>
   <xsl:template match="DBCFIXED">
      <!-- Flatten out the DBCFIXED node. -->
      <xsl:apply-templates select="@*|node()"/>
   </xsl:template>
   <xsl:template match="DBCDATE[ . = '']">
     <!-- Pick-up the default date from the parent DBCDATE. -->
      <xsl:copy>
        <xsl:value-of select="
        ../preceding-sibling::DBCFIXED/
        DBCDATE[ . != ''][1]" />        
      </xsl:copy>
   </xsl:template>
   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

相关内容

  • 没有找到相关文章

最新更新