2017-07-18 79 views
0

我是XSL转换的新手,我想将XML A转换为XML B.任何有关在XSLT或xquery中实现这一点的建议。我尝试使用上MSISDN 的for-each-组,但仍无法达到it.Any示例代码以开始与将XML文件平坦化为树状结构分组字段

XML答:

<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进行分组,然后遍历int它的领域。下面是我尝试

<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

“*我尝试在msisdn上使用for-each-group *”发布您的尝试,以便我们可以修复它,而不必从头开始为您编写代码。 –

+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提供的工具,只是我已经使用在正确的上下文(match="Output")右人口(select="response")。如果您很难理解这一点,请尝试使用XSLT 2.0分组教程。由于您似乎想要处理组中的每个项目两次,因此我已经使用模式来完成该操作,因此要构建CombinedUsage我已经使用了默认模式,以构建SharedUsaged我已经使用了不同的模式。剩下的就是为输入中的元素编写模板,将其映射到输出中的元素,并确保不希望某些模式的结果中的元素不能通过使用空模板复制。

+0

感谢您的解决方案Martin。我需要XML B中的两个使用标签,因为XML A中有两个不同的msisdn。 –

+0

@NaveenzRock,我已更正'usage'元素的位置,不知何故,我是第一次尝试把它放在'for-each-group'外面,当你需要它的时候。 –

+0

你能给我解释一下吗?我的逻辑走得没那么复杂(至少对我来说)。我想理解这个逻辑并建立最终的xsl。您分享的网站是好的。直接我们可以编辑东西 –