bugfix> xml > 投稿

フラットなxmlを階層的なxml構造に変換する必要があります。ターゲット要素は、ソースxmlとは異なるレベルでマッピングする必要があります。 XMLを複数回ループしてターゲットxmlを作成することになりました。属性名で//を使用することも良い考えではありません。なぜなら、xmlは巨大であり、パフォーマンスの問題につながる可能性があるからです。

xsltをより良い方法で記述できるかどうかを理解したいと思います。

以下に簡単な例を紹介しようとしました。

どんなアイデアやヘルプも歓迎します。

入力xml:

<result>
    <program>
        <c i='0' d='Policy'>
            <c i='14' d='LOB'>
                <m i='CR TOT TERR TERM PREM' d='CR TOT TERR TERM PREM' v='-17277' />
                <m i='CR TOT TERR NET PREM' d='CR TOT TERR NET PREM' v='-14935' />
                <m i='CR TOT TERR GAP PREM' d='CR TOT TERR GAP PREM' v='294' />
                <m i='CR TOT TERR FINAL ADJ PREM' d='CR TOT TERR FINAL ADJ PREM'
                    v='-17571' />
                <m i='CR QUOTE OPTION ID' d='CR QUOTE OPTION ID'
                    v='Quote0001' />
                <m i='CR TOT TERR COMMISSION' d='CR TOT TERR COMMISSION' v='-2635.65' />
                <m i='CR TOT TERR ACTUAL PREM' d='CR TOT TERR ACTUAL PREM' v='-17571' />
                <m i='CR TOT TERM PREM' d='CR TOT TERM PREM' v='-881154' />
                <m i='CR TOT TAXES AND SRCHRG' d='CR TOT TAXES AND SRCHRG' v='-892.14' />
                <m i='CR TOT STATE SRCHRG' d='CR TOT STATE SRCHRG' v='-896.14' />
                <m i='CR TOT PREM ADJ' d='CR TOT PREM ADJ' v='0' />
                <m i='CR TOT PREM' d='CR TOT PREM' v='-897026.14' />
                <m i='CR TOT NET PREM' d='CR TOT NET PREM' v='-761713' />
                <m i='CR TOT GAP PREM' d='CR TOT GAP PREM' v='14980' />
                <m i='CR TOT FINAL ADJ PREM' d='CR TOT FINAL ADJ PREM' v='-896134' />
                <m i='CR TOT COMMISSION' d='CR TOT COMMISSION' v='-134420.1' />
                <m i='CR TOT ADDL COV TERM PREM' d='CR TOT ADDL COV TERM PREM' v='-879465' />
                <m i='CR TOT ADDL COV NET PREM' d='CR TOT ADDL COV NET PREM' v='-760253.59999999998' />
                <m i='CR TOT ADDL COV GAP PREM' d='CR TOT ADDL COV GAP PREM' v='14951' />
                <m i='CR TOT ADDL COV FINAL ADJ PREM' d='CR TOT ADDL COV FINAL ADJ PREM'
                    v='-894416' />
                <m i='CR TOT ADDL COV COMMISSION' d='CR TOT ADDL COV COMMISSION'
                    v='-134162.40000000002' />
                <m i='CR TOT ADDL COV ACTUAL PREM' d='CR TOT ADDL COV ACTUAL PREM'
                    v='-894416' />
                <m i='CR TOT ACTUAL PREM' d='CR TOT ACTUAL PREM' v='-896134' />
                <m i='CR STATE SRCHRG NAME' d='CR STATE SRCHRG NAME' v='FL Comml Prop Fire Marshall' />
                <m i='CR FL POLICY SRCHRG NAME' d='CR FL POLICY SRCHRG NAME' v='FL Emergency Mgmt Praparedness' />
                <m i='CR FL POLICY SRCHRG' d='CR FL POLICY SRCHRG' v='4' />
                <m i='CR EMPL THEFT ANNUAL RATE' d='CR EMPL THEFT ANNUAL RATE' v='1.144' />
                <m i='CR EMPL THEFT ANNUAL PREM' d='CR EMPL THEFT ANNUAL PREM' v='15401' />
            </c>
        </c>
    </program>
</result>

xslt:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns="urn:company:esb:services:Pricing:v01">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes">
    </xsl:output>
    <xsl:strip-space elements="*"/>
    <xsl:template match="/result/program/c">
        <xsl:element name="pricing-response">
            <dummy>
                <policy>
                    <xsl:for-each select="c">
                        <xsl:variable name='strComp'>
                            <xsl:value-of select='@i'/>
                        </xsl:variable>
                        <xsl:if test="@d ='CrimeLine' ">
                            <policy-output>
                                <xsl:for-each select="m">
                                    <xsl:variable name='strComp'>
                                        <xsl:value-of select='@i'/>
                                    </xsl:variable>
                                    <xsl:if test="$strComp ='CR QUOTE OPTION ID' ">
                                        <quote-option-id>
                                            <xsl:value-of select='@v'/>
                                        </quote-option-id>
                                    </xsl:if>
                                    <xsl:if test="$strComp ='CR TOT TAXES AND SRCHRG' ">
                                        <total-taxsurcharge-amt>
                                            <amount>
                                                <xsl:value-of select='@v'/>
                                            </amount>
                                        </total-taxsurcharge-amt>
                                    </xsl:if>
                                    <xsl:if test="$strComp ='CR TOT PREM' ">
                                        <total-premium-amt>
                                            <amount>
                                                <xsl:value-of select='@v'/>
                                            </amount>
                                        </total-premium-amt>
                                    </xsl:if>
                                </xsl:for-each>
                                <taxsurcharge-summary>
                                    <taxsurcharge>
                                        <taxsurcharge-identifier>State</taxsurcharge-identifier>
                                        <xsl:for-each select="m">
                                            <xsl:variable name='strComp'>
                                                <xsl:value-of select='@i'/>
                                            </xsl:variable>
                                            <xsl:if test="$strComp ='CR TOT STATE SRCHRG' ">
                                                <taxsurcharge-amt>
                                                    <amount>
                                                        <xsl:value-of select='@v'/>
                                                    </amount>
                                                </taxsurcharge-amt>
                                            </xsl:if>
                                            <xsl:if test="$strComp ='CR STATE SRCHRG NAME' ">
                                                <taxsurcharge-name>
                                                    <xsl:value-of select='@v'/>
                                                </taxsurcharge-name>
                                            </xsl:if>
                                            <xsl:if test="$strComp ='CR STATE SRCHRG CODE' ">
                                                <taxsurcharge-code>
                                                    <xsl:value-of select='@v'/>
                                                </taxsurcharge-code>
                                            </xsl:if>
                                        </xsl:for-each>
                                    </taxsurcharge>
                                </taxsurcharge-summary>
                            </policy-output>
                        </xsl:if>
                    </xsl:for-each>
                </policy>
            </dummy>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

出力XML:

<?xml version="1.0" encoding="UTF-8"?>
<pricing-response xmlns="urn:company:esb:services:Pricing:v01">
    <dummy>
        <policy>
            <policy-output>
                <quote-option-id>Quote0001</quote-option-id>
                <total-taxsurcharge-amt>
                    <amount>-892.14</amount>
                </total-taxsurcharge-amt>
                <total-premium-amt>
                    <amount>-897026.14</amount>
                </total-premium-amt>
                <taxsurcharge-summary>
                    <taxsurcharge>
                        <taxsurcharge-identifier>State</taxsurcharge-identifier>
                        <taxsurcharge-amt>
                            <amount>-896.14</amount>
                        </taxsurcharge-amt>
                        <taxsurcharge-name>FL Comml Prop Fire Marshall</taxsurcharge-name>
                    </taxsurcharge>
                </taxsurcharge-summary>
            </policy-output>
        </policy>
    </dummy>
</pricing-response>

回答 1 件
  • 実際、特に汎用言語からのXSLTの新規参入者は、XML文書を、ノードを for:each で反復する必要がある反復可能なものとして扱います  および if  元のソースを変換するためのロジック。ただし、XSLTでは、テンプレートを考慮してツリーを再作成する必要があります。

    2番目の c のレベルまで歩くと、次のことを考慮してください  レベルを設定し、XPath呼び出しで条件付きで値を取得します。デフォルトのネームスペース urn:company:esb:services:Pricing:v01 がなければ、スクリプトはずっと短くなっていたでしょう。  ルートで <xsl:element ... namespace=...> が必要  新しく割り当てられた各ノード上。

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes" method="xml" version="1.0" encoding="UTF-8"/>
      <xsl:strip-space elements="*"/>
      <xsl:template match="/result/program/c">
        <pricing-response xmlns="urn:company:esb:services:Pricing:v01">
            <dummy>
                <policy>
                    <xsl:apply-templates select="c"/>     
                </policy>
            </dummy>
        </pricing-response>
      </xsl:template>
      <xsl:template match="c">
        <xsl:element name="policy-output" namespace="urn:company:esb:services:Pricing:v01">
          <xsl:element name="quote_option" namespace="urn:company:esb:services:Pricing:v01">
            <xsl:value-of select="m[@i='CR QUOTE OPTION ID']/@v"/>
          </xsl:element>
          <xsl:element name="total-taxsurcharge-amt" namespace="urn:company:esb:services:Pricing:v01">
            <xsl:element name="amount" namespace="urn:company:esb:services:Pricing:v01">
                <xsl:value-of select="m[@i='CR TOT TAXES AND SRCHRG']/@v"/>
            </xsl:element>
          </xsl:element>
          <xsl:element name="total-premium-amt" namespace="urn:company:esb:services:Pricing:v01">
            <xsl:element name="amount" namespace="urn:company:esb:services:Pricing:v01">
                <xsl:value-of select="m[@i='CR TOT PREM']/@v"/>
            </xsl:element>
          </xsl:element>
          <xsl:element name="taxsurcharge-summary" namespace="urn:company:esb:services:Pricing:v01">
            <xsl:element name="taxsurcharge" namespace="urn:company:esb:services:Pricing:v01">
                <xsl:element name="taxsurcharge-identifier" namespace="urn:company:esb:services:Pricing:v01">State</xsl:element>
                <xsl:element name="taxsurcharge-amt" namespace="urn:company:esb:services:Pricing:v01">
                    <xsl:element name="amount" namespace="urn:company:esb:services:Pricing:v01">
                        <xsl:value-of select="m[@i='CR TOT STATE SRCHRG']/@v"/>
                    </xsl:element>
                </xsl:element>
                <xsl:element name="taxsurcharge-name" namespace="urn:company:esb:services:Pricing:v01">
                    <xsl:value-of select="m[@i='CR STATE SRCHRG NAME']/@v"/>
                </xsl:element>
            </xsl:element>
          </xsl:element>
        </xsl:element>
      </xsl:template>
     </xsl:stylesheet>
    
    

    XSLT Fiddle Demo

あなたの答え