2015-09-30 4 views
1

XSLT новичок (спасибо заранее)XSLT 2.0, шаблоны и соответствующие

У меня есть файл XML, содержащий данные о платеже. Я пытаюсь преобразовать его в XML-формат, используемый банком. XML должен отличаться в зависимости от типа платежа (срочный платеж/провод, стандартный платеж/ETF или ручной платеж). В данном файле возможны несколько платежей. Вот пример исходного XML (упрощенный, две сделки, как тот же самый тип оплаты)

<Payments> 
<Payment xmlns:ns="urn:com.bank/paymentconnector"> 
    <Payment_Detail> 
    <Payment_Info> 
    <ns:PAYMENT_Payment_Memo>Payment Info1</ns:PAYMENT_Payment_Memo> 
    <ns:PAYMENT_Payment_Amount>1111</ns:PAYMENT_Payment_Amount> 
    <ns:PAYMENT_Type>Wire</ns:PAYMENT_Type> 
    <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</ns:PAYEE_Bank_Country> 
    </Payee_Data> 
    </Payment_Detail> 
    </Payment> 
<Payment> 
    <Payment_Detail> 
    <Payment_Info> 
    <ns:PAYMENT_Payment_Memo>Payment Info2</ns:PAYMENT_Payment_Memo> 
    <ns:PAYMENT_Payment_Amount>22222</ns:PAYMENT_Payment_Amount> 
    <ns:PAYMENT_Type>Wire</ns:PAYMENT_Type> 
    <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</ns:PAYEE_Bank_Country> 
</Payee_Data> 
</Payment_Detail> 
</Payments> 

Вот моя (упрощенный) выход

<?xml version="1.0" encoding="UTF-8"?> 
    <!-- urgent payment--> 
    <urgent_payment_header> 
    <header_fields/> 
    </urgent_payment_header> 
    <paymentrec> 
    <recordType>5</recordType> 
    <payerAccNum>1111-11111111</payerAccNum> 
    <!-- (other fields)--> 
    </paymentrec> 
    <paymentrec> 
    <recordType>5</recordType> 
    <payerAccNum></payerAccNum> 
    <!-- continue with any other urgent payments in the file--> 
    </paymentrec> 
    <urgent_control_fields> 
    </urgent_control_fields> 

    <!-- standard payment--> 
    <standard_payment_header> 
    <header_fields/> 
    </standard_payment_header> 
    <paymentrec> 
    <recordType>4</recordType> 
    <payerAccNum>1111-11111111</payerAccNum> 
    <!-- (other fields)--> 
    </paymentrec> 
    <paymentrec> 
    <recordType>4</recordType> 
    <payerAccNum></payerAccNum> 
    <!-- continue with any other standard payments in the file--> 
    </paymentrec> 
    <standard_control_fields> 
    </standard_control_fields> 

    <!-- catch all payments--> 
    <catchall_payment_header> 
    <header_fields/> 
    </catchall_payment_header> 
    <paymentrec> 
    <recordType>3</recordType> 
    <payerAccNum>1111-11111111</payerAccNum> 
<!-- (other fields)--> 
    </paymentrec> 
    <paymentrec> 
    <recordType>3</recordType> 
    <payerAccNum></payerAccNum> 
    <!-- continue with any other catchall payments in the file--> 
    </paymentrec> 
    <catchall_control_fields> 
    </catchall_control_fields> 

мой XSLT работает, когда все платежи в исходный файл является одним и тем же типом (все срочные, все стандартные, все другие типы) с одним заголовком, перечислены записи платежей, а затем одна контрольная запись

Однако, когда типы платежей смешиваются (например, один срочный и один стандарт), то только заголовок, первый узел и управление запись записывается на выход. Если файл содержит срочный платеж/провод и стандартный платеж, я хочу выход быть

вот мой (упрощенный XSLT)

<!-- Begin writing the output--> 
    <xsl:template match="Payments"> 
    <xsl:choose> 
     <xsl:when test="Payment/Payment_Detail/Payment_Info[ns:PAYMENT_Type != 'Wire']"> 
       <xsl:call-template select="Payment-Header"/> 
       <xsl:apply-templates select="Payment"/> 
       <xsl:call-templates select="Payment-Control-Standard"/> 
     </xsl:when> 
     <xsl:when test="Payment/Payment_Detail/Payment_Info[ns:PAYMENT_Type = 'Wire']"> 
       <xsl:call-template select="Payment-Header"/> 
       <xsl:apply-templates select="Payment"/> 
       <xsl:call-template name="Payment-Control-Urgent"/> 
     </xsl:when> 
     <xsl:otherwise> 
       <xsl:call-template name="Payment-Header"/> 
       <xsl:apply-templates select="Payment"/> 
       <xsl:call-template name="Payment-Control-CatchAll"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 


<xsl:template match="Payment"> 
    <xsl:choose> 
     <xsl:when test="Payment_Detail/Payment_Info[ns:PAYMENT_Type != 'Wire']"> 
       <xsl:call-template name="Payment-Standard"/> 
     </xsl:when> 
     <xsl:when test="Payment_Detail/Payment_Info[ns:PAYMENT_Type = 'Wire']"> 
       <xsl:call-template name="Payment-Urgent"/> 
     </xsl:when> 
     <xsl:otherwise> 
       <xsl:call-template name="Payment-CatchAll"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

<!-- End writing the output--> 

<!-- Begin template details--> 

    <xsl:template name="Payment-Header"> 
     <header> 
      (header fields, details not important) 
     </header> 
    </xsl:template> 


<xsl:template name="Payment-Control-Standard"> 
    <control> 
     <numberOfPayments>count of standard payments in the file</numberOfPayments> 
     <sumOfPayments>sum of standard payments in the file</sumOfPayments> 
    </control> 
</xsl:template> 

<xsl:template name="Payment-Control-Urgent"> 
    <control> 
     <numberOfPayments>count of urgent payments in the file</numberOfPayments> 
     <sumOfPayments>sum of urgent payments in the file</sumOfPayments> 
    </control> 
</xsl:template> 

<xsl:template name="Payment-Control-CatchAll"> 
    <control> 
     <numberOfPayments>count of catch all payments in the file</numberOfPayments> 
     <sumOfPayments>sum of catch all payments in the file</sumOfPayments> 
    </control> 
</xsl:template> 

<xsl:template name="Payment-Standard"> 
<paymentrec> 
     (payment fields, details not important) 
</paymentrec> 
</xsl:template> 

<xsl:template name="Payment-Urgent"> 
    <paymentrec> 
     (payment fields, details not important)   
    </paymentrec> 
</xsl:template> 

<xsl:template name="Payment-CatchAll"> 
    <paymentrec> 
     (payment fields, details not important)   
    </paymentrec> 
</xsl:template> 
+0

Код типа '' просто даст синтаксическую ошибку XSLT или XPath об этой непревзойденной закрывающей квадратной скобке ']'. –

+0

Есть также многочисленные ошибки в исходном XML. ns: не определено, PAYMENT_Type закрыт PAYMENT_Currency во многих местах, у вас есть закрывающий тег wpc: PAYEE_Bank_Country для открытия тега ns: PAYEE_Bank_Country. Потратьте время, чтобы сначала опубликовать действительный XML, прежде чем просить нас попытаться исправить проблемы, поскольку сначала нам нужно исправить все эти ошибки. –

+0

Извините. Я раскалывал фактический источник xml/xslt, чтобы попытаться упростить его понимание и сделать проблему хуже. (Отредактировано) – Jay

ответ

0

Вещь с

<xsl:template match="Payments"> 
    <xsl:choose> 
     <xsl:when test="Payment/Payment_Detail/Payment_Info/ns:PAYMENT_Type != 'Wire']"> 

что он оценивается как истинный, если существует не менее одинPayment элемент с PAYMENT_Type не «провод». Скорее всего, это не то, чего вы хотите.

Если одна запись на входе должна быть преобразована в одну запись на выходе и ничего не должно быть сделано, тогда вам не нужен общий шаблон für Payments. Итак, я бы предложил полностью удалить шаблон для Payments и сделать важный материал внутри шаблона Payment.

Внутри текущего шаблона для Payment я вижу две проблемы:

  • Как Мартин Honnen уже pointet, вы имеете синтаксическую ошибку там: ] излишни.

  • Вызвав шаблон через xsl: apply-templates, ваш контекстный узел уже Payment, поэтому Payment в выражениях XPath неверен.

+0

Исправлен источник xml/xslt – Jay

+0

Может быть 1 платеж или несколько платежей. прямо сейчас, если у них одинаковый тип оплаты, все работает нормально. это если есть несколько платежей, но разные типы, это проблема – Jay

+0

Я получил это. И я думаю, это из-за структуры вашего XSLT. В вашем шаблоне для «Платежей» вы сначала проверяете, есть ли в источнике какой-либо «платеж» с «ns: PAYMENT_Type», не являющийся «Проводом». Если да, шаблоны внутри первого 'xsl: when' вызываются, и ничего больше не делается. То есть в этом случае инструкции внутри других 'xsl: when' и' xsl: иначе' никогда не будут выполнены. Это ошибка дизайна вашего XSLT. Опять же, я бы предложил сделать все внутри шаблона «Payment». – cis

0

Хотя я все еще не уверен на 100%, я получаю то, что вы хотите, я попробую еще раз.

Я немного упростил ваш ввод XML при добавлении другого случая для Способа оплаты. Она теперь выглядит так:

<Payments xmlns:ns="urn:com.bank/paymentconnector"> 
    <Payment> 
     <Payment_Detail> 
      <Payment_Info> 
       <ns:PAYMENT_Type>Wire</ns:PAYMENT_Type> 
      </Payment_Info> 
      <Payer_Data> 
       <ns:PAYER_Company_Name>Company1</ns:PAYER_Company_Name> 
      </Payer_Data> 
     </Payment_Detail> 
    </Payment> 

    <Payment> 
     <Payment_Detail> 
      <Payment_Info> 
       <ns:PAYMENT_Type>Wire</ns:PAYMENT_Type> 
      </Payment_Info> 
      <Payer_Data> 
       <ns:PAYER_Company_Name>Company2</ns:PAYER_Company_Name> 
      </Payer_Data> 
     </Payment_Detail> 
    </Payment> 

    <Payment> 
     <Payment_Detail> 
      <Payment_Info> 
       <ns:PAYMENT_Type>Something else than Wire</ns:PAYMENT_Type> 
      </Payment_Info> 
      <Payer_Data> 
       <ns:PAYER_Company_Name>Company3</ns:PAYER_Company_Name> 
      </Payer_Data> 
     </Payment_Detail> 
    </Payment> 

    <Payment> 
     <Payment_Detail> 
      <Payment_Info> 
       <ns:PAYMENT_Type>Something else than Wire</ns:PAYMENT_Type> 
      </Payment_Info> 
      <Payer_Data> 
       <ns:PAYER_Company_Name>Company4</ns:PAYER_Company_Name> 
      </Payer_Data> 
     </Payment_Detail> 
    </Payment> 
</Payments> 

Теперь, если я вас правильно, вы хотите заголовок для каждого отдельного способа оплаты и некоторые детали для каждой записи ниже.Я бы предложил сделать это в обмен на каждую группу, как так:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ns="urn:com.bank/paymentconnector" 
version="2.0"> 
    <xsl:template match="/"> 
     <any_root_element> 
      <xsl:for-each-group select="//Payment" group-by="Payment_Detail/Payment_Info/ns:PAYMENT_Type"> 
      <xsl:choose> 
       <xsl:when test="current-grouping-key() = 'Wire'"> 
        <header_for_wire/> 
        <xsl:for-each select="current-group()"> 
         <paymentrec> 
         <details> 
         Paid by <xsl:value-of select="Payment_Detail/Payer_Data/ns:PAYER_Company_Name"/> 
         </details> 
         </paymentrec> 
        </xsl:for-each> 
       </xsl:when> 

       <xsl:when test="current-grouping-key() = 'Something else than Wire'"> 
        <header_for_something_else_than_wire/> 
        <xsl:for-each select="current-group()"> 
        <paymentrec> 
         <details> 
         Paid by <xsl:value-of select="Payment_Detail/Payer_Data/ns:PAYER_Company_Name"/> 
         </details> 
        </paymentrec>  
        </xsl:for-each> 
       </xsl:when> 
      </xsl:choose> 

     </xsl:for-each-group> 

     </any_root_element> 
    </xsl:template> 
</xsl:transform> 

Что приведет к этому XML:

<any_root_element> 
    <header_for_wire/> 
    <paymentrec> 
     <details> Paid by Company1</details> 
    </paymentrec> 
    <paymentrec> 
     <details> Paid by Company2</details> 
    </paymentrec> 
    <header_for_something_else_than_wire/> 
    <paymentrec> 
     <details> Paid by Company3</details> 
    </paymentrec> 
    <paymentrec> 
     <details> Paid by Company4</details> 
    </paymentrec> 
</any_root_element> 

Является ли это более или менее то, что вы хотите? (Конечно, если детали являются общими, вы можете создать для него шаблон, чтобы избежать повторения.)

Смежные вопросы