金融系统中BERTLV的解析,更改、增加、删除TAG的实现

金融系统中BER-TLV是一个常用的数据交换协议,TLV是(TAG-LENGTH-VALUE)的缩写,其具体的规范在ISO7616-4中有明确的定义。目前简单描述下关于TLV的编码规则,下文所有的数据表示均为16进制编码。

TAG域:

TAG域的第一个字节编码

TAG域的第二个字节编码

其中注意第一个字节的第六位,其分为基本数据对象和结构数据对象。简单解释下基本数据对象和结构数据对象,简单举两个例子,下面几个都是符合tlv编码的数据流:

70069F3803010203

9F3803010203

可以看到,70 TAG的值(value)域也是由TLV结构组成的。

而9F38 TAG的值域则是由简单数据构成(010203)不需要符合TLV结构编码。

基于这个原则,TLV可以设计成多层嵌套的关系。

例如:

6F30840E325041592E5359532E4444463031A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101

如果解析嵌套,可以如下表示(以缩进关系表示嵌套关系)

6F(TAG)

  30(6F的LEN域)

    840E325041592E5359532E4444463031A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101(6F的VALUE域)

    84(TAG)

      0E(84的LEN域)

        325041592E5359532E4444463031(84的VALUE域)

    A5(TAG)

      1E(A5的LEN域)

        BF0C1B61194F08A000000333010101500A50424F43204445424954870101(A5的VALUE域)

        BF0C(TAG)

         1B(BFOC的LEN域)

          61194F08A000000333010101500A50424F43204445424954870101(BFOC的VALUE域)

          61(TAG)

           19(61的LEN域)

               4F08A000000333010101500A50424F43204445424954870101(61的VALUE域)

             4F(TAG)

              08(4F的LEN域)  

                A000000333010101(4F的VALUE域)

                                   50(TAG)

              0A(50的LEN域)

                50424F43204445424954(50的VALUE域)

            87(TAG)

              01(87的LEN域)

                01(87的VALUE域)

讲完了TAG域,下面简单说明下长度(LEN)域,长度域相比TAG域简单多了,ISO的原文就能很好的说明问题了。

讲完了TLV的基本结构,现在来讲讲目前设计的实现。目前网上实现的TLV代码也很多,但是很多是基于解析的,没有搜索到有关是基于修改的。

因为TVL存在嵌套结构,因此一个多层嵌套的TLV结构被更改了,可能会导致一连串的TLV结构LEN域和值域都需要修改。还是上文的那个6FTLV结构为例,如果底层的87被改了,那么除了和他同级别的50、4F和简单结构的84是不需要改变的,其包含了他的所有嵌套结构的TLV结构,都需要改变(6F\A5\BFOC\61),而不巧,本人碰到了多次需要改变该值的情况,特别如果是长度变化了,那整个TLV结构的长度都需要重新算,比较痛苦,因此就设计了以下的模式。

上面是简单介绍TLV和一些前因后果,下面是实现。

====================================================================

从上文的分析中可以看到,针对一个复合的tlv结构,那么他可以抽象成存在他的值域全是他的下层TLV结构。而一个简单的TLV机构,则可以抽象成他没有下层TLV结构。而真对一个TLV数据串,就可以抽象成多个复杂TLV机构或者简单TLV结构的首尾拼接,各个TLV段之间是平级的。

这个抽象是不是很像二叉树,因此,就考虑用二叉树的方式去实现这个结构,目前定义的为左边的节点均是他的兄弟(同一级别),右边的节点均是他的儿子(他的下级),由此针对上文的6F,抽象成树的结构就是如下图示:

因此,如果我们如果需要求一个简单结构的值,则只需要将值直接放在节点上,如果需要求一个复杂结构的值,只需要把它的儿子做一个左右中遍历(将简单机构直接连接成tlv串,如果是复杂结构则直接取之前的串加上自己的TAG和LENGTH)就能够获得他的value了。

如果是增加一个TLV结构,例如我需要再插入一个A5,其值为9F380101,在原有的84后A5前,则我需要将这个A5首先构造成一个串,然后将左子树连新的A5,将老的A5变为新的A5的左子树,其变化图如下:

                                        

当然如果是简单结构,那就直接是树的节点的插入,这边就不在说了。

当然,删除也就是插入的逆向操作,这里也不说了。(嘿嘿,偷懒下了)

最后,程序的输出可以是XML或者JSON的显示,由于目前项目的选择,列子就以JSON的表示了:

插入之前:

[
   {
      "funccode" : 0
   },
   [
      {
         "6F" : "840E325041592E5359532E4444463031A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101",
         "tlvstr" : "6F30840E325041592E5359532E4444463031A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101"
      },
      [
         {
            "84" : "325041592E5359532E4444463031",
            "tlvstr" : "840E325041592E5359532E4444463031"
         },
         {
            "A5" : "BF0C1B61194F08A000000333010101500A50424F43204445424954870101",
            "tlvstr" : "A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101"
         },
         [
            {
               "BF0C" : "61194F08A000000333010101500A50424F43204445424954870101",
               "tlvstr" : "BF0C1B61194F08A000000333010101500A50424F43204445424954870101"
            },
            [
               {
                  "61" : "4F08A000000333010101500A50424F43204445424954870101",
                  "tlvstr" : "61194F08A000000333010101500A50424F43204445424954870101"
               },
               [
                  {
                     "4F" : "A000000333010101",
                     "tlvstr" : "4F08A000000333010101"
                  },
                  {
                     "50" : "50424F43204445424954",
                     "tlvstr" : "500A50424F43204445424954"
                  },
                  {
                     "87" : "01",
                     "tlvstr" : "870101"
                  }
               ]
            ]
         ]
      ]
   ]
]

插入之后

[
   [
      {
         "6F" : "840E325041592E5359532E4444463031A5049F380101A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101",
         "tlvstr" : "6F36840E325041592E5359532E4444463031A5049F380101A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101"
      },
      [
         {
            "84" : "325041592E5359532E4444463031",
            "tlvstr" : "840E325041592E5359532E4444463031"
         },
         {
            "A5" : "9F380101",
            "tlvstr" : "A5049F380101"
         },
         [
            {
               "9F38" : "01",
               "tlvstr" : "9F380101"
            }
         ],
         {
            "A5" : "BF0C1B61194F08A000000333010101500A50424F43204445424954870101",
            "tlvstr" : "A51EBF0C1B61194F08A000000333010101500A50424F43204445424954870101"
         },
         [
            {
               "BF0C" : "61194F08A000000333010101500A50424F43204445424954870101",
               "tlvstr" : "BF0C1B61194F08A000000333010101500A50424F43204445424954870101"
            },
            [
               {
                  "61" : "4F08A000000333010101500A50424F43204445424954870101",
                  "tlvstr" : "61194F08A000000333010101500A50424F43204445424954870101"
               },
               [
                  {
                     "4F" : "A000000333010101",
                     "tlvstr" : "4F08A000000333010101"
                  },
                  {
                     "50" : "50424F43204445424954",
                     "tlvstr" : "500A50424F43204445424954"
                  },
                  {
                     "87" : "01",
                     "tlvstr" : "870101"
                  }
               ]
            ]
         ]
      ]
   ],
   {
      "funccode" : 0
   }
]
原文地址:https://www.cnblogs.com/highkgao/p/3968086.html