Файл XML с фиксированной длиной с использованием XSLT (логика сложной позиции) - PullRequest
1 голос
/ 07 марта 2019

У нас есть требование, по которому нужно конвертировать XML в файл фиксированной длины.Первая запись в качестве заголовка, и после этого у нас есть фактические записи. От 2-х записей мы должны применить логику, которая упомянута ниже:
1. После длины 45, рассмотрим 10 цифр 0000001000, какой будет последняя цифранужно проверить и заменить, следуя приведенной ниже таблице:

      "For Positive Amount: (0000001000)   - (000000100{)             
      {= 0                                          
      A = 1                                       
      B = 2                                      
      c = 3                                      
      D = 4                                     
      E = 5                                      
      F = 6                                     
      G = 7                                      
      H = 8                                     
      I = 9 

У меня не так много идей, поэтому я создал маленький XSLT, попросите кого-нибудь, пожалуйста, помогите с этим.

Ввод:

 <?xml version='1.0' encoding='utf-8'?>
<ZR>
<INPUT>
   <I_FIL>ERES</I_FIL>
  </INPUT>
  <TABLES>
   <T_ER>
    <item>
        <DATA> HEADER1111111122222222333333344456</DATA>
    </item>
    <item>
         <DATA>778944    D4E2   EA     1234567891 2018-11-060000001000EA 
       0000000000000100001020D04YA30TRE0000000XXXYYY 300{  P 2018-11-05</DATA>
    </item>
    <item>
        <DATA>987654    D4E2   EA     1987654321 2018-11-060000002001EA 
       0000000000000100001020D04YA30UUU0000000XXXLRB 100{  P 2018-11-05</DATA>
    </item>
                .
                .
                .
                .
                .
                .
                .
                .
</T_ER>
</TABLES>
</ZR>

XSLT:

       <?xml version="1.0" encoding="UTF-8"?>
   <xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:fn="http://www.w3.org/2005/xpath-functions" >
    <xsl:output omit-xml-declaration="yes"/>
     <xsl:param name="break" select="'&#xA;'" />

       <xsl:template match="/">
      <xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA"/> 
    <xsl:value-of select="$break" />
    </xsl:template>
   </xsl:stylesheet>

Ожидаемый результат:

     HEADER1111111122222222333333344456
        778944    D4E2   EA     1234567891 2018-11-06000000100{EA 
       0000000000000100001020D04YA30TRE0000000XXXYYY 300{  P 2018-11-05
    987654    D4E2   EA     1987654321 2018-11-06000000200AEA 
       0000000000000100001020D04YA30UUU0000000XXXLRB 100{  P 2018-11-05
    .
    .
    .
    .

Ответы [ 2 ]

1 голос
/ 07 марта 2019

Похоже, вы просто хотите заменить 55-й символ на основе вашей карты, чтобы вы могли сделать это ...

<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA"/> 
<xsl:value-of select="$break" />
<xsl:for-each select="ZR/TABLES/T_ER/item[position() > 1]/DATA">
  <xsl:variable name="char" select="substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1)" />
  <xsl:value-of select="concat(substring(., 1, 54), $char, substring(., 56))" />
  <xsl:value-of select="$break" />
</xsl:for-each>
</xsl:template>

Это будет работать в XSLT 1.0.

Решение XSLT 2.0 может быть таким ...

<xsl:template match="/">
<xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA,
                      ZR/TABLES/T_ER/item[position() > 1]/DATA/concat(substring(., 1, 54), substring('{ABCDEFGHI', number(substring(., 55, 1)) + 1, 1), substring(., 56))" 
              separator="&#xA;" />
</xsl:template>

В XSLT 3.0 вы могли бы потенциально использовать map с преимуществом простого расширения, если бы вы хотеливместо этого рассмотрим два или более символов:

<xsl:stylesheet version="3.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:fn="http://www.w3.org/2005/xpath-functions" >

  <xsl:output omit-xml-declaration="yes"/>
  <xsl:param name="break" select="'&#xA;'" />

  <xsl:variable name="chars" as="map(xs:string, xs:string)">
    <xsl:map>
      <xsl:map-entry key="'0'" select="'{'"/>
      <xsl:map-entry key="'1'" select="'A'"/>
      <xsl:map-entry key="'2'" select="'B'"/>
      <xsl:map-entry key="'3'" select="'C'"/>
      <xsl:map-entry key="'4'" select="'D'"/>
      <xsl:map-entry key="'5'" select="'E'"/>
      <xsl:map-entry key="'6'" select="'F'"/>
      <xsl:map-entry key="'7'" select="'G'"/>
      <xsl:map-entry key="'8'" select="'H'"/>
      <xsl:map-entry key="'9'" select="'I'"/>
    </xsl:map>
  </xsl:variable>

  <xsl:template match="/">
    <xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA,
                          ZR/TABLES/T_ER/item[position() > 1]/DATA/concat(substring(., 1, 54), $chars(substring(., 55, 1)), substring(., 56))" separator="&#xA;" />
  </xsl:template>
</xsl:stylesheet>

Вероятно, в XSLT 3.0 гораздо более приятный путь, так что надеюсь, что Мартин Хоннен скоро скажет ....

1 голос
/ 07 марта 2019

Ну, используя функции string-length, substring и translate для ваших спецификаций, это может быть достигнуто как:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output omit-xml-declaration="yes" />
<xsl:param name="break" select="'&#xA;'" />

 <xsl:template match="/">
    <xsl:value-of select="ZR/TABLES/T_ER/item[1]/DATA" />
    <xsl:value-of select="$break" />

    <xsl:for-each select="ZR/TABLES/T_ER/item[position() != 1]">

        <xsl:variable name="length" select="string-length(substring(DATA,0,46))" />
        <xsl:variable name="tenNumbers" select="substring(DATA, ($length + 1), 10)"/>
        <xsl:variable name="charToReplace" select="translate(substring($tenNumbers, string-length($tenNumbers), 1),'0123456789','{ABCDEFGHI')" />

        <xsl:value-of select="concat(substring(DATA,0,46), substring(DATA, ($length + 1), 9), $charToReplace, substring(DATA,($length+11),(string-length(DATA) + 1)))"/>
        <xsl:value-of select="$break" />
    </xsl:for-each>

 </xsl:template>
</xsl:stylesheet>
...