SAP JCo анализирует XML в IDOC с расширениями полей

у меня возникли проблемы с анализом XML в IDOC с помощью библиотеки SAP JCo. Я знаю, что мне нужно подключение к системе SAP, которая предоставляется.

Вот мой тестовый код Gradle:

    when:
    JCoIDocServer server = JCoIDoc.getServer(sapProperties.get("jco.server.progid"))

    IDocXMLProcessor xmlProcessor = JCoIDoc.getIDocFactory().getIDocXMLProcessor()
    IDocDocumentList iDocDocumentList = xmlProcessor.parse(server.getIDocRepository(), getClass().getResourceAsStream("/data/DEBMAS-406868135.XML"), IDocXMLProcessor.PARSE_IGNORE_UNKNOWN_FIELDS)

Соединение работает, но JCo обнаруживает несоответствие в моем XML (экспортировано из SAP, без ручных изменений!), которое, по-видимому, вызвано полями расширения SAP:

com.sap.conn.idoc.IDocParseException: (7) IDOC_ERROR_PARSE_FAILURE: IDoc type extension ZDEBMAS3 within the EDI_DC40 control record segment does not match the IDoc-XML root tag <DEBMAS05>:

состояние = READING_ENDTAG, charPosition = 852, lineNumber = 24, columnNumber = 19

Как видите, я пытался использовать параметры парсера XML, но это не помогло.

Что мне нужно сделать, чтобы поля расширения принимались IDocParser?

Обновление 1 Здесь вы можете найти анонимный XML-файл IDOC.

<?xml version="1.0"?>
<DEBMAS05>
    <IDOC BEGIN="1">
        <EDI_DC40 SEGMENT="1">
            <TABNAM><![CDATA[EDI_DC40]]></TABNAM>
            <MANDT>100</MANDT>
            <DOCNUM>0000000406868135</DOCNUM>
            <DOCREL>750</DOCREL>
            <STATUS>12</STATUS>
            <DIRECT>1</DIRECT>
            <OUTMOD>2</OUTMOD>
            <IDOCTYP>DEBMAS05</IDOCTYP>
            <CIMTYP>ZDEBMAS3</CIMTYP>
            <MESTYP><![CDATA[Z_DEBMAS2]]></MESTYP>
            <SNDPOR>XXX</SNDPOR>
            <SNDPRT>LS</SNDPRT>
            <SNDPRN><![CDATA[P02_100]]></SNDPRN>
            <RCVPOR>INTERNET</RCVPOR>
            <RCVPRT>LS</RCVPRT>
            <RCVPRN>INTERNET</RCVPRN>
            <CREDAT>20190503</CREDAT>
            <CRETIM>085059</CRETIM>
            <SERIAL>20190503081911</SERIAL>
        </EDI_DC40>
        <E1KNA1M SEGMENT="1">
            <MSGFN>004</MSGFN>
            <KUNNR>XXX</KUNNR>
            <ANRED>XXX</ANRED>
            <BBBNR>0000000</BBBNR>
            <BBSNR>00000</BBSNR>
            <BUBKZ>0</BUBKZ>
            <KTOKD>XXX</KTOKD>
            <LAND1>XX</LAND1>
            <NAME1>XXX</NAME1>
            <ORT01>XXX</ORT01>
            <ORT02>XXX</ORT02>
            <PSTLZ>XXX</PSTLZ>
            <REGIO>XXX</REGIO>
            <SORTL>XXX</SORTL>
            <SPRAS>XXX</SPRAS>
            <STRAS>XXX</STRAS>
            <LZONE>0000000001</LZONE>
            <UMJAH>0000</UMJAH>
            <JMZAH>000000</JMZAH>
            <JMJAH>0000</JMJAH>
            <KATR3>XXX</KATR3>
            <KATR7>XXX</KATR7>
            <KATR8>XXX</KATR8>
            <STKZN>X</STKZN>
            <UMSA1>0</UMSA1>
            <HZUOR>00</HZUOR>
            <CIVVE>X</CIVVE>
            <SPRAS_ISO>DE</SPRAS_ISO>
            <ZE1BPAD SEGMENT="1">
                <PARNR>XXX</PARNR>
                <TITLE_P>XXX</TITLE_P>
                <FIRSTNAME>XXX</FIRSTNAME>
                <LASTNAME>XXX</LASTNAME>
                <SORT1_P>XXX</SORT1_P>
                <NAMCOUNTRY>DE</NAMCOUNTRY>
                <NAMCTRYISO>DE</NAMCTRYISO>
                <LANGU_P>D</LANGU_P>
                <LANGUP_ISO>DE</LANGUP_ISO>
            <C_O_NAME>XXX</C_O_NAME>
            <DISTRICT>XXX</DISTRICT>
            <CITY>XXX</CITY>
            <POSTL_COD1>XXX</POSTL_COD1>
            <REGION>XXX</REGION>
            <TRANSPZONE>0000000001</TRANSPZONE>
            <STREET>XXX.</STREET>
            <HOUSE_NO>XXX</HOUSE_NO>
            <PERS_GROUP>XXX</PERS_GROUP>
            <ADDR_GROUP>XXX</ADDR_GROUP>
            <E_MAIL>XXX</E_MAIL>
        </ZE1BPAD>
        <E1KNA11 SEGMENT="1">
            <KNURL>/</KNURL>
            <J_1KFREPRE>/</J_1KFREPRE>
            <J_1KFTBUS>/</J_1KFTBUS>
            <J_1KFTIND>/</J_1KFTIND>
            <PSOIS>/</PSOIS>
            <PSON1>/</PSON1>
            <PSON2>/</PSON2>
            <PSON3>/</PSON3>
            <PSOVN>/</PSOVN>
            <PSOTL>/</PSOTL>
            <PSOO1>/</PSOO1>
            <PSOO2>/</PSOO2>
            <PSOO3>/</PSOO3>
            <PSOO4>/</PSOO4>
            <PSOO5>/</PSOO5>
            <STCD5>/</STCD5>
            <SUFRAMA>/</SUFRAMA>
            <RG>/</RG>
            <EXP>/</EXP>
            <UF>/</UF>
            <RGDATE>/</RGDATE>
            <RIC>/</RIC>
            <RNE>/</RNE>
            <RNEDATE>/</RNEDATE>
            <CNAE>/</CNAE>
            <LEGALNAT>/</LEGALNAT>
            <CRTN>/</CRTN>
            <ICMSTAXPAY>/</ICMSTAXPAY>
            <INDTYP>/</INDTYP>
            <TDT>/</TDT>
            <COMSIZE>/</COMSIZE>
            <DECREGPC>/</DECREGPC>
            <CVP_XBLCK>/</CVP_XBLCK>
        </E1KNA11>
        <E1KNVVM SEGMENT="1">
            <MSGFN>XXX</MSGFN>
            <VKORG>XXX</VKORG>
            <VTWEG>XXX</VTWEG>
            <SPART>XXX</SPART>
            <VERSG>1</VERSG>
            <KALKS>XXX</KALKS>
            <KONDA>XXX</KONDA>
            <AWAHR>XXX</AWAHR>
            <INCO1>FH</INCO1>
            <INCO2>XXX</INCO2>
            <ANTLF>XXX</ANTLF>
            <KZTLF>XXX</KZTLF>
            <LPRIO>XXX</LPRIO>
            <WAERS>XXX</WAERS>
            <KTGRD>XXX</KTGRD>
            <ZTERM>XXX</ZTERM>
            <VWERK>XXX</VWERK>
            <KVGR4>XXX</KVGR4>
            <KVGR5>XXX</KVGR5>
            <UEBTO>XXX</UEBTO>
            <UNTTO>XXX</UNTTO>
            <PVKSM>XXX</PVKSM>
            <PODTG>XXX</PODTG>
            <BLIND>/</BLIND>
            <CARRIER_NOTIF>/</CARRIER_NOTIF>
            <CVP_XBLCK_V>/</CVP_XBLCK_V>
            <INCOV>/</INCOV>
            <INCO2_L>/</INCO2_L>
            <INCO3_L>/</INCO3_L>
            <ZE1KNVV SEGMENT="1">
                <HASH_CODE>XXX</HASH_CODE>
            </ZE1KNVV>
            <E1KNVPM SEGMENT="1">
                <MSGFN>XXX</MSGFN>
                <PARVW>XXX</PARVW>
                <KUNN2>XXX</KUNN2>
                <PARZA>XXX</PARZA>
            </E1KNVPM>
            <E1KNVPM SEGMENT="1">
                <MSGFN>XXX</MSGFN>
                <PARVW>XXX</PARVW>
                <KUNN2>XXX</KUNN2>
                <PARZA>XXX</PARZA>
            </E1KNVPM>
            <E1KNVPM SEGMENT="1">
                <MSGFN>XXX</MSGFN>
                <PARVW>WE</PARVW>
                <KUNN2>XXX</KUNN2>
                <PARZA>XXX</PARZA>
            </E1KNVPM>
        </E1KNVVM>
        <E1KNB1M SEGMENT="1">
            <MSGFN>XXX</MSGFN>
            <BUKRS>XXX</BUKRS>
            <ZUAWA>XXX</ZUAWA>
            <AKONT>XXX</AKONT>
            <ZWELS>XXX</ZWELS>
            <ZTERM>XXX</ZTERM>
            <VZSKZ>XXX</VZSKZ>
            <ZINDT>XXX</ZINDT>
            <ZINRT>XXX</ZINRT>
            <FDGRV>XXX</FDGRV>
            <VLIBB>XXX</VLIBB>
            <VRSZL>XXX</VRSZL>
            <VRSPR>XXX</VRSPR>
            <VERDT>XXX</VERDT>
            <WEBTR>XXX</WEBTR>
            <DATLZ>XXX</DATLZ>
            <XZVER>XXX</XZVER>
            <KULTG>XXX</KULTG>
            <PERNR>XXX</PERNR>
            <GMVKZD>/</GMVKZD>
            <AVSND>/</AVSND>
            <SMTP_ADDR>/</SMTP_ADDR>
            <CVP_XBLCK_B>/</CVP_XBLCK_B>
            <E1KNB5M SEGMENT="1">
                <MSGFN>XXX</MSGFN>
                <MAHNA>XXX</MAHNA>
                <MADAT>XXX</MADAT>
                <MAHNS>XXX</MAHNS>
                <GMVDT>XXX</GMVDT>
            </E1KNB5M>
            <E1KNB5M SEGMENT="1">
                <MSGFN>XXX</MSGFN>
                <MABER>XXX</MABER>
                <MAHNA>XXX</MAHNA>
                <MADAT>XXX</MADAT>
                <MAHNS>XXX</MAHNS>
                <GMVDT>XXX</GMVDT>
            </E1KNB5M>
        </E1KNB1M>
        <E1KNKKM SEGMENT="1">
            <MSGFN>XXX</MSGFN>
            <KKBER>XXX</KKBER>
            <KLIMK>XXX</KLIMK>
            <KNKLI>XXX</KNKLI>
            <CTLPC>XXX</CTLPC>
            <DTREV>XXX</DTREV>
            <SBGRP>XXX</SBGRP>
            <NXTRV>XXX</NXTRV>
            <PAYDB>XXX</PAYDB>
            <REVDB>XXX</REVDB>
            <SBDAT>XXX</SBDAT>
            <DBEKR>XXX</DBEKR>
            <DBMON>XXX</DBMON>
        </E1KNKKM>
    </E1KNA1M>
    <EDI_DS40 SEGMENT="1">
        <MANDT>XXX</MANDT>
        <DOCNUM>XXX</DOCNUM>
        <LOGDAT>XXX</LOGDAT>
        <LOGTIM>XXX</LOGTIM>
        <STATUS>XXX</STATUS>
        <STAMNO>XXX</STAMNO>
        <UNAME><![CDATA[BTCSD_01]]></UNAME>
        <SEGNUM>XXX</SEGNUM>
    </EDI_DS40>
    <EDI_DS40 SEGMENT="1">
        <MANDT>XXX</MANDT>
        <DOCNUM>XXX</DOCNUM>
        <LOGDAT>XXX</LOGDAT>
        <LOGTIM>XXX</LOGTIM>
        <STATUS>XXX</STATUS>
        <STAMQU>XXX</STAMQU>
        <STAMID>XXX</STAMID>
        <STAMNO>XXX</STAMNO>
        <STATYP>XXX</STATYP>
        <STAPA1>XXX</STAPA1>
        <STAPA2>XXX</STAPA2>
        <STAPA3>XXX</STAPA3>
        <STAPA4>XXX</STAPA4>
        <STATXT><![CDATA[&, &, &, &.]]></STATXT>
        <UNAME><![CDATA[BTCSD_01]]></UNAME>
        <SEGNUM>XXX</SEGNUM>
    </EDI_DS40>
    <EDI_DS40 SEGMENT="1">
        <MANDT>XXX</MANDT>
        <DOCNUM>XXX</DOCNUM>
        <LOGDAT>XXX</LOGDAT>
        <LOGTIM>XXX</LOGTIM>
        <STATUS>XXX</STATUS>
        <STAMQU>XXX</STAMQU>
        <STAMID>XXX</STAMID>
        <STAMNO>XXX</STAMNO>
        <STAPA1><![CDATA[SAP_ALE_Z_DEBMAS2]]></STAPA1>
        <STAPA2>XXX</STAPA2>
        <STATXT>XXX</STATXT>
        <UNAME><![CDATA[BTCSD_01]]></UNAME>
        <REPID>XXX</REPID>
        <SEGNUM>XXX</SEGNUM>
    </EDI_DS40>
    <EDI_DS40 SEGMENT="1">
        <MANDT>XXX</MANDT>
        <DOCNUM>XXX</DOCNUM>
        <LOGDAT>XXX</LOGDAT>
        <LOGTIM>XXX</LOGTIM>
        <STATUS>XXX</STATUS>
        <STAMNO>XXX</STAMNO>
        <UNAME><![CDATA[BTCSD_01]]></UNAME>
        <REPID>RBDMOIND</REPID>
        <SEGNUM>XXX</SEGNUM>
    </EDI_DS40>
</IDOC>

Update 2

Просто для тестирования я попытался создать IDOC вручную с помощью следующего фрагмента кода.

    JCoIDocServer server = JCoIDoc.getServer(sapProperties.get("jco.server.progid"))
    IDocDocument idoc = JCoIDoc.getIDocFactory().createIDocDocument(server.getIDocRepository(), "DEBMAS05")
    idoc.setValue("MANDT", 100)
    idoc.setValue("IDOCTYP", "DEBMAS05")
    idoc.setValue("CIMTYP", "ZDEBMAS3")
    idoc.setIDocNumber("0000000406868135")


    JCoIDocSegment segment = idoc.rootSegment.addChild("E1KNA1M")

    segment.addChild("ZE1BPAD")

Это приводит к той же ошибке, что и при использовании xmlProcessor.

Но если я изменю этот лок, добавив тип расширения IDOC

IDocDocument idoc = JCoIDoc.getIDocFactory().createIDocDocument(server.getIDocRepository(), "DEBMAS05","ZDEBMAS3")

ошибка исчезает.

Обновление 3

Кажется, я смешиваю две проблемы. Первый возникает, когда JCo анализирует XML, вызывая описанное здесь исключение.

В JCo 3.0.17 вызывающая реализация находится в DefaultIDocXMLParser в строке 1321.

   if (cimType.length() > 0 && !cimType.equals(this.openTags.getFirst()) || cimType.length() == 0 && !iDocType.equals(this.openTags.getFirst())) {
                            throw new IDocParseException("IDoc type " + (cimType.length() > 0 ? "extension " + cimType : iDocType) + " within the EDI_DC40 control record segment does not match the IDoc-XML root tag <" + (String)this.openTags.getFirst() + ">", this.state.name(), this.charPosition, this.lineNumber, this.columnNumber, (String)null, 0);
                        }

Чтобы избежать этого исключения, можно удалить элемент, который вызывает то же исключение, что и программно созданный IDOC без типа расширения.

Теперь возникает вопрос: как можно настроить XMLParser для приема расширений?


person flexguse    schedule 14.05.2019    source источник
comment
Не могли бы вы показать нам содержимое файла XML?   -  person Trixx    schedule 15.05.2019


Ответы (2)


Теперь, после того как вы добавили содержимое IDoc-XML, я бы сказал, что синтаксический анализатор действительно прав со своим сообщением об ошибке. Содержимое файла IDoc-XML нарушает спецификацию IDoc-XML от SAP. В этом случае корневой тег должен быть ‹ZDEBMAS3› вместо ‹DEBMAS05›.

Корневой тег должен описывать наиболее подробное значение типа IDoc, а это означает, что он должен содержать значение поля IDOCTYP, если больше нет доступных определяющих CIMTYP. Но как только появляется дополнительный CIMTYP, корневой тег должен вместо этого содержать значение поля CIMTYP. Странное правило, но это правило.

Так что ошибается не анализатор IDoc-XML, а тот, кто создал файл IDoc-XML. Я боюсь, что этот синтаксический анализатор IDoc-XML не может принять эти ошибочные данные IDoc-XML. Вам необходимо исправить программное обеспечение, которое создает этот файл IDoc-XML.

person Trixx    schedule 16.05.2019
comment
Большое спасибо за ваш ответ! В итоге я написал собственный SAXParser, вдохновленный IAF ibissource github.com/ibissource/iaf/blob/master/sap/src/main/java/nl/nn/, который может генерировать IDOC из наш неверный XML. К сожалению, у меня нет возможности создать корректный IDoc-XML. - person flexguse; 16.05.2019
comment
Спасибо, что поделился. Самостоятельный разбор - вариант, конечно. Однако я бы предпочел предлагаемые классы от SAP, если это возможно. Я думаю, что реализация SAP здесь быстрее и, скорее всего, с меньшим количеством ошибок в более сложных случаях. Этот синтаксический анализатор от SAP специально создан для IDoc-XML, который определяет несколько правил, с которыми стандартный XML-парсер не может работать в готовом виде. Например, подумайте о правилах экранирования специальных символов, которые необходимы, когда сегменты или поля IDoc содержат символы, которые обычно разрешены для IDoc, но не для стандартного XML. Но я не хочу быть убийцей здесь. ;-) - person Trixx; 16.05.2019

Вам необходимо передать действительный считыватель или входной поток. Файл XML не является ресурсом для класса. Так что, пожалуйста, попробуйте

new FileInputStream(new File("/data/DEBMAS-406868135.XML"))

вместо?

person Trixx    schedule 15.05.2019
comment
В моем модульном тесте файл XML является ресурсом класса, и он отлично найден. - person flexguse; 15.05.2019
comment
Я пытаюсь анонимизировать XML IDOC, и вы найдете его в моем исходном вопросе. - person flexguse; 15.05.2019