Пройдите по дереву xmlns c и удалите пространства имен в ESQL - PullRequest
0 голосов
/ 15 января 2020

РЕДАКТИРОВАТЬ: Удаляя xmlns, я пытался решить проблему, когда узел сопоставления не анализировал входное сообщение с полями, содержащими пространство имен. Тело ввода задается вручную, а не из XSD. Когда пространства имен удаляются из файла вручную, все работает. Но когда я использую скрипт E SQL, он перестает работать по неизвестной мне причине.

Здравствуйте, у меня есть сообщение XML, из которого мне нужно удалить пространства имен. Я пытаюсь рекурсивно пройтись по дереву XML и удалить атрибут xmlns, если он существует. К сожалению, когда я пытаюсь сделать SET element = NULL, мой l oop не будет go до следующего элемента MOVE element NEXTSIBLING. Я пытался сделать DELETE FIELD element, но это дает тот же эффект.

Вот мой полный код:

CREATE COMPUTE MODULE test_Compute1
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
     DECLARE blobMsg BLOB Environment.BLOB.BLOB ;
     CREATE LASTCHILD OF Environment.Variables.inpMsg DOMAIN ('XMLNSC') NAME 'XMLNSC';
     CREATE LASTCHILD OF Environment.Variables.inpMsg.XMLNSC PARSE(blobMsg OPTIONS FolderBitStream CCSID InputRoot.Properties.CodedCharSetId FORMAT 'XMLNSC');
     SET Environment.Variables.statusRes.statusCode = Environment.Variables.inpMsg.XMLNSC.errorResponse.httpCode;
     SET Environment.Variables.statusRes.detail = Environment.Variables.inpMsg.XMLNSC.errorResponse.httpMessage;
     SET Environment.Variables.statusRes.additionalStatus.detail = Environment.Variables.inpMsg.XMLNSC.errorResponse.moreInformation;
     CALL NavigateTree(Environment.Variables.inpMsg.XMLNSC);
    RETURN TRUE;
END;

CREATE PROCEDURE NavigateTree(IN root REFERENCE)
BEGIN
    DECLARE element REFERENCE TO root;
    DECLARE hint CHARACTER;
    DECLARE test CHARACTER;
    SET test = '';
    SET hint = '';

    MOVE element FIRSTCHILD;
        -----------
    IF LASTMOVE(element) THEN
        SET hint = 'has children';
    ELSE
    IF FIELDNAME(element) = 'xmlns' THEN
        DELETE FIELD element;
    END IF;
    END IF;

    WHILE LASTMOVE(element) DO
        -- not working awell:
        -- DECLARE space1 NAMESPACE 'namespace1';
        -- SET element.(XML.NamespaceDecl)* = NULL;
        DECLARE nameField2 CHARACTER FIELDNAMESPACE(element);
        DECLARE nameField CHARACTER FIELDNAME(element);
        DECLARE ifhint CHARACTER;

        CALL NavigateTree(element);
        MOVE element NEXTSIBLING;
    END WHILE;
    SET hint = 'finished';

END;
   END MODULE;

У вас есть идеи, как мне это сделать?

РЕДАКТИРОВАТЬ:

CREATE COMPUTE MODULE test_Compute1
    CREATE FUNCTION Main() RETURNS BOOLEAN
    BEGIN
         DECLARE blobMsg BLOB Environment.BLOB.BLOB ;
         CREATE LASTCHILD OF Environment.Variables.inpMsg DOMAIN ('XMLNSC') NAME 'XMLNSC';
         CREATE LASTCHILD OF Environment.Variables.inpMsg.XMLNSC PARSE(blobMsg OPTIONS FolderBitStream CCSID InputRoot.Properties.CodedCharSetId FORMAT 'XMLNSC');
         SET Environment.Variables.statusRes.statusCode = Environment.Variables.inpMsg.XMLNSC.errorResponse.httpCode;
         SET Environment.Variables.statusRes.detail = Environment.Variables.inpMsg.XMLNSC.errorResponse.httpMessage;
         SET Environment.Variables.statusRes.additionalStatus.detail = Environment.Variables.inpMsg.XMLNSC.errorResponse.moreInformation;
         CALL StripNamespaces(Environment.Variables.inpMsg);
        RETURN TRUE;
    END;
    CREATE PROCEDURE StripNamespaces(IN fieldRef REFERENCE)
    BEGIN
        IF FIELDTYPE(fieldRef) IN (XMLNSC.NamespaceDecl, XMLNSC.SingleNamespaceDecl) THEN
            DELETE FIELD fieldRef;
            RETURN;
        END IF;
        DECLARE childRef REFERENCE TO fieldRef;
        MOVE childRef FIRSTCHILD;
        WHILE LASTMOVE(childRef) DO
            DECLARE currentChildRef REFERENCE TO childRef;
            MOVE childRef NEXTSIBLING;
            CALL StripNamespaces(currentChildRef);
        END WHILE;
    END;
END MODULE;

XML, который работает как входной файл, который идет на узел отображения (редактируется вручную):

<?xml version="1.0" encoding="utf-8"?>
<Receive >
    <messageData>
        <CD >
            <EXP  />
            <EXAMPLE  />
        </CD>
        <XRP >
            <EX1>
                <SEG>string</SEG>
                <SEG2>integer</SEG2>
            </EX1>
            <ARRAY>
                <AR1>string</AR1>
                <AR2 />
            </ARRAY>
            <ARRAY>
                <AR1>integer</AR1>
                <AR2 />
            </ARRAY>
        </XRP>
    </messageData>
</Receive>

XML, который не работает (узел отображения не может обработать его должным образом после того, как он прошел анализ, упомянутый выше):

<?xml version="1.0" encoding="utf-8"?>
<Receive xmlns="namespace">
    <messageData>
        <CD xmlns="namespace2">
            <EXP xmlns="namespace3" />
            <EXAMPLE xmlns="namespace3" />
        </CD>
        <XRP xmlns="namespace2">
            <EX1>
                <SEG>string</SEG>
                <SEG2>integer</SEG2>
            </EX1>
            <ARRAY>
                <AR1>string</AR1>
                <AR2 />
            </ARRAY>
            <ARRAY>
                <AR1>integer</AR1>
                <AR2 />
            </ARRAY>
        </XRP>
    </messageData>
</Receive>

В обоих случаях отладчик показывает ту же самую древовидную структуру после прохода через тот же самый синтаксический анализатор:

Variables
            inpMsg
                    XMLNSC
                            Receive
                                    messageData
                                            CD
                                                    EXP
                                                    EXAMPLE
                                            XRP
                                                    EX1
                                                            SEG:CHARACTER:string
                                                            SEG2:CHARACTER:integer
                                                    ARRAY
                                                            AR1:CHARACTER:string
                                                            AR2
                                                    ARRAY
                                                            AR1:CHARACTER:integer
                                                            AR2

1 Ответ

1 голос
/ 16 января 2020

После удаления поля вы должны выйти из рекурсивной функции.

Вот как мы это делаем:

CREATE PROCEDURE StripNamespaces(IN fieldRef REFERENCE)
BEGIN
    IF FIELDTYPE(fieldRef) IN (XMLNSC.NamespaceDecl, XMLNSC.SingleNamespaceDecl) THEN
        DELETE FIELD fieldRef;
        RETURN;
    ELSEIF FIELDNAMESPACE(fieldRef) <> '' THEN
        SET fieldRef NAMESPACE = '';
    END IF;
    DECLARE childRef REFERENCE TO fieldRef;
    MOVE childRef FIRSTCHILD;
    WHILE LASTMOVE(childRef) DO
        DECLARE currentChildRef REFERENCE TO childRef;
        MOVE childRef NEXTSIBLING;
        CALL StripNamespaces(currentChildRef);
    END WHILE;
END;
...