XSLT 2.0,模板和节点/值集

时间:2015-08-11 20:36:59

标签: xml xslt

XSLT新手(所以我提前道歉)

我有一个包含付款数据的XML文件。我试图将其转换为银行使用的xml格式。如果XML是非美元付款与美元付款,则XML需要不同。在给定文件中可以进行多次付款 这是源XML的示例(简化,一个事务)

<Payments>
 <Payment>
  <Payment_Detail>
     <Payment_Info>
        <ns:PAYMENT_Payment_Memo>Payment Info</ns:PAYMENT_Payment_Memo>
        <ns:PAYMENT_Payment_Amount>22222</ns:PAYMENT_Payment_Amount>
        <ns:PAYMENT_Currency>US Dollars</ns:PAYMENT_Currency>
        <ns:PAYMENT_Currency_Code>USD</ns:PAYMENT_Currency_Code>
        <ns:PAYMENT_Check_or_Advice_Number>0</ns:PAYMENT_Check_or_Advice_Number>
     </Payment_Info>
     <Payer_Data>
        <ns:PAYER_Company_Name>Company, LLP</ns:PAYER_Company_Name>
        <ns:PAYER_Address_Line_1>Main st</ns:PAYER_Address_Line_1>
        <ns:PAYER_Address_Line_2>Line 2</ns:PAYER_Address_Line_2>
        <ns:PAYER_City>Cleveland</ns:PAYER_City>
        <ns:PAYER_Zip_Code>11111</ns:PAYER_Zip_Code>
        <ns:PAYER_Country>US</ns:PAYER_Country>
        <ns:PAYER_Account_Number>1111-11111111</ns:PAYER_Account_Number>
        <ns:PAYER_Currency>USD</ns:PAYER_Currency>
     </Payer_Data>
     <Payee_Data>
        <ns:PAYEE_Name>Name</ns:PAYEE_Name>
        <ns:PAYEE_Bank_Name>Bank Name</ns:PAYEE_Bank_Name>
        <ns:PAYEE_Bank_Account_Name>Account Name</ns:PAYEE_Bank_Account_Name>
        <ns:PAYEE_Account_Number>1111111</ns:PAYEE_Account_Number>
        <ns:PAYEE_Masked_Account_Number>**********</ns:PAYEE_Masked_Account_Number>
        <ns:PAYEE_Account_Type>DD</ns:PAYEE_Account_Type>
        <ns:PAYEE_Routing_Transit_Number>22222</ns:PAYEE_Routing_Transit_Number>
        <ns:PAYEE_Bank_Country>US</wpc:PAYEE_Bank_Country>
     </Payee_Data>
  </Payment_Detail>
 </Payment>
</Payments>   

我的想法是/是根据货币使用不同的模板。我遇到的问题是在多次付款时确定要调用哪个模板(节点集与单个节点)

这是我的XSL(也简化)

<xsl:variable name="paymentCurrency"
   select="/Payment/Payment_Detail/Payment_Info/ns:PAYMENT_Currency_Code"/>


        <xsl:choose> 
           <xsl:when test="$paymentCurrency = 'USD'">

                   <xsl:call-template name="Payment-Domestic"/> 

           </xsl:when>    
           <xsl:otherwise>

               <xsl:call-template name="Payment-Foreign"/>

           </xsl:otherwise>

       </xsl:choose>


         <xsl:template name="Payment-Domestic">
           <xsl:for-each select="/Payments/Payment">
               <paymentrec>
                   <recordType>2</recordType>
                   <!-- insert other domestic payment fields -->
            </xsl:for-each>
        </xsl:template>

         <xsl:template name="Payment-Foreign">
           <xsl:for-each select="/Payments/Payment">
               <paymentrec>
                   <recordType>5</recordType>
                   <!-- insert other non US payment fields -->
            </xsl:for-each>
        </xsl:template>

当输入文件中有单个付款时,它会起作用,但是多个条目将变量设置为节点/值集,并且永远不会匹配。

调用不同模板的最佳方法是什么? 我不应该使用for-each吗? (将XSLT视为命令式语言也不是最聪明的想法,我知道)

由于

编辑回答评论/问题 XSLT 2.0,示例输出(简化如下)

(国外付款)

<paymentrec>
  <recordType>5</recordType>
  <payerAccNum>1111-11111111</payerAccNum>
  <Currency/>
  (other fields)
</paymentrec>

(美元付款)

<paymentrec>
  <recordType>2</recordType>
  <payerAccNum>1111-11111111</payerAccNum>
  <payAmount/>
  (other fields)
</paymentrec>

它还引出了另一个问题: 如果我有3-4个字段作为国内支付的标题添加(但不是外国的)。我有一个国内支付模板,但如果我在国内&#34;国内&#34;模板,它复制标题。如果我在拨打&#34;付款&#34;模板出现在国外付款中(我不想要)

2 个答案:

答案 0 :(得分:0)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://example.edu/" version="1.0">
  /* start at the root node... */
  <xsl:template match="/Payments">
    <root>
      <xsl:apply-templates select="Payment"/>
    </root>
  </xsl:template>

  /* then for each "Payment" figure out what it is, call appropriate template */
  <xsl:template match="Payment">
    <xsl:choose>
      <xsl:when test="Payment_Detail/Payment_Info/ns:PAYMENT_Currency_Code='USD'">
        <xsl:call-template name="domestic"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="foreign"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  /* note that these are "rooted" relative to the Payment element */
  <xsl:template name="domestic">
    <domestic>
    <xsl:value-of select="Payment_Detail/Payment_Info/PAYMENT_Payment_Amount"/>
    </domestic>
  </xsl:template>

  <xsl:template name="foreign">
    <TODO>
      <foreign/>
    </TODO>
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

我会使用多个这样的模板规则:

<xsl:template match="Payment[Payment_Detail/Payment_Info/ns:PAYMENT_Currency_Code='USD']">
  <usa>
    ...
  </usa>
</xsl:template>

<xsl:template match="Payment">
  <restOfTheWorld>
    ...
  </restOfTheWorld>
</xsl:template>

不需要@thrig使用的额外“路由”模板 - 模板匹配模式可以免费使用。

您的代码使用

<xsl:variable name="paymentCurrency"   select="/Payment/Payment_Detail/Payment_Info/ns:PAYMENT_Currency_Code"/>

是错误的,因为以“/”开头的路径表达式相对于文档的根目录选择,而不是相对于您当前正在处理的付款。

(虽然我们处于相对与绝对的主题,但我避免使用“国内”和“外国”这两个术语,因为您希望您的代码对美国以外的人有意义。)