【问题标题】:Walk trough xmlnsc tree and remove namespaces in ESQL遍历 xmlnsc 树并删除 ESQL 中的命名空间
【发布时间】:2020-01-17 05:34:49
【问题描述】:

编辑:通过删除 xmlns,我试图解决一个问题,即映射节点不会解析包含命名空间的字段的输入消息。输入正文是手动设置的 - 不是来自 XSD。当手动从文件中删除命名空间时,一切正常。但是当我使用 ESQL 脚本时,它会因为一些我不知道的原因而停止工作。

您好,我有需要从中删除名称空间的 XML 消息。我想要做的是递归遍历 XML 树并删除 xmlns 属性(如果存在)。不幸的是,当我尝试执行SET element = NULL 时,我的循环不会转到下一个元素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

【问题讨论】:

  • 两个消息树不一样,但是调试器不显示XML标签的命名空间,所以它们看起来是一样的。因此,当使用命名空间时,我经常使用 Trace 节点。
  • @kimbert 我有一段时间有这样的假设,调试器可能无法显示所有内容,现在我得到了确认。我将检查 Trace 节点,看看我发现了什么。谢谢!
  • 另外...如果您确定不创建 XSD,则 Mapping 节点可能是您的映射逻辑的错误选择。只需改用 ESQL - 它会一样清晰。
  • ESQL 不是一个选项(目前),因为 XML 文件有更多字段并且需要一些处理。我想那将是很多写作。听起来我必须尝试编写 XSD。

标签: ibm-integration-bus extended-sql


【解决方案1】:

删除字段后,您必须离开递归函数。

这就是我们的做法:

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;

【讨论】:

  • 感谢您的回复。这种方法有效。由于某些未知的原因,我的 Mapping 节点无论如何都不会读取这样的树,但是如果我从输入 xml 文件中手动删除 xmlns,则 Mapping 会正确地从环境变量中读取输入值。请注意,我在 Mapping 节点中手动设置了 Input。你有什么想法为什么会发生?谢谢。
  • 在不知道Environment.BLOB.BLOB 是什么的情况下,也很难看到涉及的 XSD。但我可以向您保证,映射节点可以很好地处理命名空间。您可以在映射节点前添加Trace Node 以查看确切的输入消息树。
  • 所以您的输入文件是单个 XML 文档,对吗?为什么它在环境中而不是 InputRoot 中?您可以分享问题中 XML 文件的内容吗?
  • 你是对的,我没有认真回答我的回答,因此更正了我的回答。
  • re: 删除命名空间...StripNamespaces 过程需要在消息树中的每个节点 上将命名空间显式设置为空字符串。仅仅删除命名空间声明是不够的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 2019-11-10
  • 2022-08-20
  • 2019-05-16
  • 1970-01-01
相关资源
最近更新 更多