【问题标题】:XSLT 2.0, templates and node/value setsXSLT 2.0、模板和节点/值集
【发布时间】:2015-08-11 20:36:59
【问题描述】:

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

我有一个包含付款数据的 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 个字段作为标题添加到国内付款(但不是国外)。我有一个国内支付模板,但如果我在“国内”模板中调用它,它会复制标题。如果我在调用“付款”模板时应用它,它会出现在国外付款中(我不想要)

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

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

    <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"/>
    

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

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

    【讨论】:

    • 谢谢!银行使用“外国”和“国内”这两个词......他们有一些非常奇怪的要求,我不会在这里讨论
    【解决方案2】:
    <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>
    

    【讨论】:

    • 最后一个(相关)问题)。如果我有 3-4 个字段作为标题添加到国内付款(但不是国外)。我有一个国内支付模板,但如果我在“国内”模板中调用它,它会复制标题。如果我在调用“付款”模板时应用它,它会出现在国外付款中(我不想要)
    • 没有样本输入和预期输出对我来说不清楚;例如如果混合区域付款会发生什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    相关资源
    最近更新 更多