重新排列和分组

时间:2014-03-20 14:57:53

标签: xml xslt xslt-1.0

我有一个xml文件需要通过对新节点中的元素进行分组来修改。 <account_plan><account_service><account_option>节点中每个元素的出现都必须在新节点<account_info_total_list>中进行分组 以下是输入xml的示例。我只能使用XSLT 1.0。

<?xml version="1.0" encoding="utf-8"?>
<Invoice>
<account_info>
<acct_id>12345678</acct_id>
<account_meta_data_info>
  <doc_id>100009999</doc_id>
</account_meta_data_info>
<account_plan>
  <Plans>Plan1</Plans>
  <Amount_plan>1x</Amount_plan>
  <Price_VATinclude_plan>12.10</Price_VATinclude_plan>
  <Price_VATexclude_plan>10.00</Price_VATexclude_plan>
</account_plan>
<account_plan>
  <Plans>Plan2</Plans>
  <Amount_plan>2x</Amount_plan>
  <Price_VATinclude_plan>24.20</Price_VATinclude_plan>
  <Price_VATexclude_plan>20.00</Price_VATexclude_plan>
</account_plan>
<account_service>
  <service_name>service1</service_name>
  <Amount_service>1x</Amount_service>
  <Price_VATinclude_service>12.10</Price_VATinclude_service>
  <Price_VATexclude_service>10.00</Price_VATexclude_service>
</account_service>
<account_service>
  <service_name>service2</service_name>
  <Amount_service>2x</Amount_service>
  <Price_VATinclude_service>24.20</Price_VATinclude_service>
  <Price_VATexclude_service>20.00</Price_VATexclude_service>
</account_service>
<account_option>
  <Price_VATexclude_option>10.00</Price_VATexclude_option>
  <Options>Option1</Options>
  <Amount_option>1x</Amount_option>
  <Price_VATinclude_option>12.10</Price_VATinclude_option>
</account_option>
<account_option>
  <Price_VATexclude_option>20.00</Price_VATexclude_option>
  <Options>Option2</Options>
  <Amount_option>2x</Amount_option>
  <Price_VATinclude_option>24.20</Price_VATinclude_option>
</account_option>
<account_option>
  <Price_VATexclude_option>30.00</Price_VATexclude_option>
  <Options>Option3</Options>
  <Amount_option>3x</Amount_option>
  <Price_VATinclude_option>0.72</Price_VATinclude_option>
</account_option>
<subs_base_info>
    <subscription_number>671880401</subscription_number>
    <charge_excludeVAT>63.73</charge_excludeVAT>
    <charge_includeVAT>73.29</charge_includeVAT>
    <tariff_plan>EU 4G Flat XXL(SOHO)</tariff_plan>
 </subs_base_info>
<subs_overview_info>
    <billing_cycle_his1>01/2014</billing_cycle_his1>
<subs_overview_info>
</account_info>
</Invoice>
  

输出必须如下:

<?xml version="1.0" encoding="utf-8"?>
<Invoice>
<account_info>
<acct_id>12345678</acct_id>
<account_meta_data_info>
  <doc_id>100009999</doc_id>
</account_meta_data_info>
<account_info_total_list>
  <Plans>Plan1</Plans>
  <service_name>service1</service_name>
  <Options>Option1</Options>
  <Amount_plan>1x</Amount_plan>
  <Amount_service>1x</Amount_service>
  <Amount_option>1x</Amount_option>
  <Price_VATinclude_plan>12.10</Price_VATinclude_plan>
  <Price_VATinclude_service>12.10</Price_VATinclude_service>
  <Price_VATinclude_option>12.10</Price_VATinclude_option>
  <Price_VATexclude_plan>10.00</Price_VATexclude_plan>
  <Price_VATexclude_service>10.00</Price_VATexclude_service>
  <Price_VATexclude_option>10.00</Price_VATexclude_option>
</account_info_total_list>
<account_info_total_list>
  <Plans>Plan2</Plans>
  <service_name>service2</service_name>
  <Options>Option2</Options>
  <Amount_plan>2x</Amount_plan>
  <Amount_service>2x</Amount_service>
  <Amount_option>2x</Amount_option>
  <Price_VATinclude_plan>24.20</Price_VATinclude_plan>
  <Price_VATinclude_service>24.20</Price_VATinclude_service>
  <Price_VATinclude_option>24.20</Price_VATinclude_option>
  <Price_VATexclude_plan>20.00</Price_VATexclude_plan>
  <Price_VATexclude_service>20.00</Price_VATexclude_service>
  <Price_VATexclude_option>20.00</Price_VATexclude_option>
</account_info_total_list>
<account_info_total_list>
  <Price_VATexclude_option>30.00</Price_VATexclude_option>
  <Options>Option3</Options>
  <Amount_option>3x</Amount_option>
  <Price_VATinclude_option>36.30</Price_VATinclude_option>
</account_info_total_list>
<subs_base_info>
    <subscription_number>671880401</subscription_number>
    <charge_excludeVAT>63.73</charge_excludeVAT>
    <charge_includeVAT>73.29</charge_includeVAT>
    <tariff_plan>EU 4G Flat XXL(SOHO)</tariff_plan>
 </subs_base_info>
<subs_overview_info>
    <billing_cycle_his1>01/2014</billing_cycle_his1>
<subs_overview_info>
</account_info>
</Invoice>

是否可以使用xslt 1.0执行此操作?

这是我刚刚测试的,但是无法正常工作,我哪里出错?

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="account_info">
<xsl:apply-templates select="acct_id | account_meta_data_info"/>
<xsl:call-template name="aggregate"/>
</xsl:template>
<xsl:template name="aggregate">
<xsl:param name="i" select="1"/>
<xsl:if test="$i &lt;= count(account_plan) or 
$i &lt;= count(account_service) or $i &lt;= count(account_option)">
    <account_info_total_list>
     <xsl:apply-templates select="account_plan[$i] | account_service[$i] | account_option[$i]"/>
    </account_info_total_list>
    <xsl:call-template name="aggregate">
        <xsl:with-param name="i" select="$i + 1"/>
    </xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="account_plan | account_service | account_option">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="account_info">
<xsl:apply-templates select="subs_base_info| subs_overview_info"/>
<xsl:call-template name="test"/>
</xsl:template>
<xsl:template name="test">
    <xsl:call-template name="test">
    </xsl:call-template>
</xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

以这种方式试试吗?

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="account_info">
    <xsl:apply-templates select="acct_id | account_meta_data_info"/>
    <xsl:call-template name="aggregate"/>
</xsl:template>

<xsl:template name="aggregate">
    <xsl:param name="i" select="1"/>
    <xsl:if test="$i &lt;= count(account_plan) or $i &lt;= count(account_service) or $i &lt;= count(account_option)">
        <account_info_total_list>
            <xsl:apply-templates select="account_plan[$i] | account_service[$i] | account_option[$i]"/>
        </account_info_total_list>
        <xsl:call-template name="aggregate">
            <xsl:with-param name="i" select="$i + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

编辑:

要匹配您的示例输出,您需要再添加一个模板:

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

附录:

要处理输入末尾的<subs_base_info><subs_overview_info>元素,请尝试:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="account_info">
    <xsl:apply-templates select="acct_id | account_meta_data_info"/>
    <xsl:call-template name="aggregate"/>
    <xsl:apply-templates select="subs_base_info |subs_overview_info"/>
</xsl:template>

<xsl:template name="aggregate">
    <xsl:param name="i" select="1"/>
    <xsl:if test="$i &lt;= count(account_plan) or $i &lt;= count(account_service) or $i &lt;= count(account_option)">
        <account_info_total_list>
            <xsl:apply-templates select="account_plan[$i] | account_service[$i] | account_option[$i]"/>
        </account_info_total_list>
        <xsl:call-template name="aggregate">
            <xsl:with-param name="i" select="$i + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

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

</xsl:stylesheet>