XML文件从平面到树结构分组字段

时间:2017-07-18 14:53:30

标签: xml xslt xquery xslt-2.0

我是XSL转换的新手,我想将XML A转换为XML B.任何在XSLT或xquery中实现此目的的建议。我尝试在msisdn上使用for-each-group 但仍然无法实现它。任何以

开头的示例代码

XML A:

<Output>
<response>
    <msisdn>27832007509</msisdn>
    <bearer>DATA</bearer>
    <comb_charged_units>4223777792</comb_charged_units>
    <comb_cnt>288</comb_cnt>
    <shared_voice_duration>0</shared_voice_duration>
    <shared_data_volume>8728127</shared_data_volume>
    <shared_voice_cnt>0</shared_voice_cnt>
    <shared_data_cnt>89</shared_data_cnt>
</response>
<response>
    <msisdn>27832007509</msisdn>
    <bearer>VOICE</bearer> 
    <comb_charged_units>477792</comb_charged_units>
    <comb_cnt>281</comb_cnt>
    <shared_voice_duration>17268127877</shared_voice_duration>
    <shared_data_volume>0</shared_data_volume>
    <shared_voice_cnt>87887</shared_voice_cnt>
    <shared_data_cnt>0</shared_data_cnt>
</response>
<response>
    <msisdn>27832229588</msisdn>
    <bearer>DATA</bearer>
    <comb_charged_units>11898</comb_charged_units>
    <comb_cnt>33</comb_cnt>
    <shared_voice_duration>0</shared_voice_duration>
    <shared_data_volume>3445</shared_data_volume>
    <shared_voice_cnt>0</shared_voice_cnt>
    <shared_data_cnt>78</shared_data_cnt>
</response>
<response>
    <msisdn>27832229588</msisdn>
    <bearer>VOICE</bearer>
    <comb_charged_units>45</comb_charged_units>
    <comb_cnt>12</comb_cnt>
    <shared_voice_duration>789</shared_voice_duration>
    <shared_data_volume>0</shared_data_volume>
    <shared_voice_cnt>23</shared_voice_cnt>
    <shared_data_cnt>0</shared_data_cnt>
</response>

XML B:

<UsageHistoryResponse>
<usage>
    <MSISDN>27832007509</MSISDN>
    <CombinedUsage>
        <usage_info>
            <bearer>DATA</bearer>
            <bearer_units>288</bearer_units>
            <bearer_units_uom>Sessions</bearer_units_uom>
            <bearer_usage>4223777792</bearer_usage>
            <bearer_usage_uom>bytes</bearer_usage_uom>
        </usage_info>
        <usage_info>
            <bearer>VOICE</bearer>
            <bearer_units>281</bearer_units>
            <bearer_units_uom>Calls</bearer_units_uom>
            <bearer_usage>477792</bearer_usage>
            <bearer_usage_uom>Seconds</bearer_usage_uom>
        </usage_info>
    </CombinedUsage>
    <SharedUsage>
        <usage_info>
            <bearer>DATA</bearer>
            <bearer_units>89</bearer_units>
            <bearer_units_uom>Sessions</bearer_units_uom>
            <bearer_usage>8728127</bearer_usage>
            <bearer_usage_uom>bytes</bearer_usage_uom>
        </usage_info>
        <usage_info>
            <bearer>VOICE</bearer>
            <bearer_units>87887</bearer_units>
            <bearer_units_uom>Calls</bearer_units_uom>
            <bearer_usage>17268127877</bearer_usage>
            <bearer_usage_uom>Seconds</bearer_usage_uom>
        </usage_info>
    </SharedUsage>
</usage>
<usage>
    <MSISDN>27832229588</MSISDN>
    <CombinedUsage>
        <usage_info>
            <bearer>DATA</bearer>
            <bearer_units>33</bearer_units>
            <bearer_units_uom>Sessions</bearer_units_uom>
            <bearer_usage>11898</bearer_usage>
            <bearer_usage_uom>bytes</bearer_usage_uom>
        </usage_info>
        <usage_info>
            <bearer>VOICE</bearer>
            <bearer_units>12</bearer_units>
            <bearer_units_uom>Calls</bearer_units_uom>
            <bearer_usage>45</bearer_usage>
            <bearer_usage_uom>Seconds</bearer_usage_uom>
        </usage_info>
    </CombinedUsage>
    <SharedUsage>
        <usage_info>
            <bearer>DATA</bearer>
            <bearer_units>78</bearer_units>
            <bearer_units_uom>Sessions</bearer_units_uom>
            <bearer_usage>3445</bearer_usage>
            <bearer_usage_uom>bytes</bearer_usage_uom>
        </usage_info>
        <usage_info>
            <bearer>VOICE</bearer>
            <bearer_units>23</bearer_units>
            <bearer_units_uom>Calls</bearer_units_uom>
            <bearer_usage>789</bearer_usage>
            <bearer_usage_uom>Seconds</bearer_usage_uom>
        </usage_info>
    </SharedUsage>
</usage>

我的想法是先将msisdn分组,然后遍历它的字段。以下是我的尝试

<xsl:template match="/">
    <tns:UsageHistoryResponse>
        <xsl:for-each select="/Output/response">
            <tns:usage>
                <xsl:for-each-group select="." group-by="ns0:msisdn">
                    <tns:MSISDN>
                    <xsl:value-of select="current-grouping-key()"/></tns:MSISDN>
                </xsl:for-each-group>
            </tns:usage>
        </xsl:for-each>
    </tns:UsageHistoryResponse>
</xsl:template>

1 个答案:

答案 0 :(得分:0)

这是一个解决方案,展示了如何实现分组和添加两个包装元素:

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

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="Output">
        <UsageHistoryResponse>         
            <xsl:for-each-group select="response" group-by="msisdn">
              <usage>
                <MSISDN>
                    <xsl:value-of select="current-grouping-key()"/>
                </MSISDN>  
                <CombinedUsage>
                    <xsl:apply-templates select="current-group()"/>
                </CombinedUsage>
                <SharedUsage>
                    <xsl:apply-templates select="current-group()" mode="shared"/>
                </SharedUsage>
              </usage>
            </xsl:for-each-group>
        </UsageHistoryResponse> 
    </xsl:template>

    <xsl:template match="response" mode="#default shared">
        <usage_info>
            <xsl:apply-templates mode="#current"/>
        </usage_info>
    </xsl:template>

    <xsl:template match="msisdn" mode="#all"/>

    <xsl:template match="response/*[starts-with(local-name(), 'shared')]"/>

    <xsl:template match="response/*[starts-with(local-name(), 'comb')]" mode="shared"/>

    <xsl:template match="comb_cnt">
        <bearer_units>
            <xsl:apply-templates/>
        </bearer_units>
    </xsl:template>

</xsl:transform>

http://xsltransform.net/bEzjRKb/1显示它提供了

<?xml version="1.0" encoding="UTF-8"?>
<UsageHistoryResponse>
   <usage>
      <MSISDN>27832007509</MSISDN>
      <CombinedUsage>
         <usage_info>
            <bearer>DATA</bearer>
            <comb_charged_units>4223777792</comb_charged_units>
            <bearer_units>288</bearer_units>
         </usage_info>
         <usage_info>
            <bearer>VOICE</bearer>
            <comb_charged_units>477792</comb_charged_units>
            <bearer_units>281</bearer_units>
         </usage_info>
      </CombinedUsage>
      <SharedUsage>
         <usage_info>
            <bearer>DATA</bearer>
            <shared_voice_duration>0</shared_voice_duration>
            <shared_data_volume>8728127</shared_data_volume>
            <shared_voice_cnt>0</shared_voice_cnt>
            <shared_data_cnt>89</shared_data_cnt>
         </usage_info>
         <usage_info>
            <bearer>VOICE</bearer>
            <shared_voice_duration>17268127877</shared_voice_duration>
            <shared_data_volume>0</shared_data_volume>
            <shared_voice_cnt>87887</shared_voice_cnt>
            <shared_data_cnt>0</shared_data_cnt>
         </usage_info>
      </SharedUsage>
   </usage>
   <usage>
      <MSISDN>27832229588</MSISDN>
      <CombinedUsage>
         <usage_info>
            <bearer>DATA</bearer>
            <comb_charged_units>11898</comb_charged_units>
            <bearer_units>33</bearer_units>
         </usage_info>
         <usage_info>
            <bearer>VOICE</bearer>
            <comb_charged_units>45</comb_charged_units>
            <bearer_units>12</bearer_units>
         </usage_info>
      </CombinedUsage>
      <SharedUsage>
         <usage_info>
            <bearer>DATA</bearer>
            <shared_voice_duration>0</shared_voice_duration>
            <shared_data_volume>3445</shared_data_volume>
            <shared_voice_cnt>0</shared_voice_cnt>
            <shared_data_cnt>78</shared_data_cnt>
         </usage_info>
         <usage_info>
            <bearer>VOICE</bearer>
            <shared_voice_duration>789</shared_voice_duration>
            <shared_data_volume>0</shared_data_volume>
            <shared_voice_cnt>23</shared_voice_cnt>
            <shared_data_cnt>0</shared_data_cnt>
         </usage_info>
      </SharedUsage>
   </usage>
</UsageHistoryResponse>

所以有些工作需要重命名元素,这可以通过添加模板来实现,然后你似乎也想添加一些数据,我不知道那些数据在哪里

<bearer_usage_uom>Seconds</bearer_usage_uom>

应该取自。

至于解释:我已经根据需要使用了for-each-group,并且作为XSLT 2.0为分组提供的工具,只有我在正确的上下文中使用了正确的群体(select="response")( match="Output")。如果您很难理解,那么请尝试使用XSLT 2.0分组教程。由于您似乎想要处理组中的每个项目两次,我已经使用模式来执行此操作,因此要构建CombinedUsage我已使用默认模式,以构建我使用过的SharedUsaged一种不同的模式。其余的是为输入中的元素编写模板,以映射到输出中的元素,并确保不使用空模板复制特定模式的结果中不需要的元素。