ASG
IBM
Zystems
Cressida
Icon
Netflexity
 
  MQSeries.net
Search  Search       Tech Exchange      Education      Certifications      Library      Info Center      SupportPacs      LinkedIn  Search  Search                                                                   FAQ  FAQ   Usergroups  Usergroups
 
Register  ::  Log in Log in to check your private messages
 
RSS Feed - WebSphere MQ Support RSS Feed - Message Broker Support

MQSeries.net Forum Index » WebSphere Message Broker (ACE) Support » Removing empty elements in output XML

Post new topic  Reply to topic
 Removing empty elements in output XML « View previous topic :: View next topic » 
Author Message
TonyD
PostPosted: Sun Apr 04, 2004 11:27 pm    Post subject: Removing empty elements in output XML Reply with quote

Knight

Joined: 15 May 2001
Posts: 540
Location: New Zealand

Is there any way to omit empty elements (e.g. <City></City>) from an output XML message without specifically testing whether the element is empty?
Back to top
View user's profile Send private message Send e-mail
martinrydman
PostPosted: Mon Apr 05, 2004 12:14 am    Post subject: Reply with quote

Centurion

Joined: 30 Jan 2004
Posts: 139
Location: Gothenburg, Sweden

Hi,

To the best of my knowledge, no there isn't. I hav solved this problem in the past by writing a recursive PROCEDURE that visits each element generically and removes it if it's empty.

Hope this helps!

/Martin
Back to top
View user's profile Send private message
Yanghui
PostPosted: Tue Apr 13, 2004 8:51 am    Post subject: Reply with quote

Disciple

Joined: 08 May 2002
Posts: 151
Location: Dublin, Ireland

Hi, there,

It seems it's not that straight forward to remove those empty tags. I tried

Set reference = NULL;

and

DETACH reference;

but both ways also change <Element1></Element1> to <Element1/>.

Does anybody know why? Many thanks in advance.

Regards

-Yanghui
Back to top
View user's profile Send private message Send e-mail
Yanghui
PostPosted: Wed Apr 14, 2004 10:18 am    Post subject: Reply with quote

Disciple

Joined: 08 May 2002
Posts: 151
Location: Dublin, Ireland

Hi,

I try to call the recursive procedure to remove those empty tag but it seems only the first empty tag of each XML block removed. The rest of them still stay in the tree... By using trace, it looks like the reference jumped from one block to the next after the first empty tag is set NULL. I don't understand why. Can anybody see anything wrong in the ESQL? Many thanks in advance.

CREATE PROCEDURE RemoveEmptyElement(IN root REFERENCE)
BEGIN
DECLARE cursor REFERENCE TO root;
MOVE cursor FIRSTCHILD;
IF LASTMOVE(cursor) THEN
ELSE
IF CAST(cursor AS CHARACTER) = '' THEN
-- DELETE FIELD cursor;
SET cursor = NULL;
END IF;
END IF;
WHILE LASTMOVE(cursor) DO
CALL RemoveEmptyElement(cursor);
MOVE cursor NEXTSIBLING;
END WHILE;
END;
Back to top
View user's profile Send private message Send e-mail
martinrydman
PostPosted: Thu Apr 15, 2004 12:50 am    Post subject: Reply with quote

Centurion

Joined: 30 Jan 2004
Posts: 139
Location: Gothenburg, Sweden

Hi!

Here's some code that actually works

Code:

-- CALL from Main:
SET OutputRoot = InputRoot;
DECLARE OutMsg REFERENCE TO OutputRoot.XML;
CALL RemoveEmptyElements(OutMsg);

-- Recursive PROCEDURE:
CREATE PROCEDURE RemoveEmptyElements(INOUT Root REFERENCE)
BEGIN
   DECLARE ClimbChildren BOOLEAN TRUE;

   IF TRIM(Root) = '' THEN
      DECLARE Elmnt REFERENCE TO Root;
      DETACH Elmnt;
      SET Elmnt = NULL;
      SET ClimbChildren = FALSE;
   END IF;      
      
   IF ClimbChildren THEN
      DECLARE NxtSibl REFERENCE TO Root;
      MOVE NxtSibl FIRSTCHILD;
      WHILE LASTMOVE(NxtSibl) DO
         DECLARE Child REFERENCE TO NxtSibl;
         MOVE NxtSibl NEXTSIBLING;
         CALL RemoveEmptyElements(Child);
      END WHILE;
   END IF;
END;



Note in particular the extra pointer NxtSibl, that is set before the recursive call. If you try to MOVE NEXTSIBLING after the call, the child to move from might have been removed, and so the MOVE fails!

HTH!

/Martin
Back to top
View user's profile Send private message
Yanghui
PostPosted: Fri Apr 16, 2004 3:00 am    Post subject: Reply with quote

Disciple

Joined: 08 May 2002
Posts: 151
Location: Dublin, Ireland

Hi, Martian,

Sorry for late reply. Just got chance to try it out.

The proble you spotted was absolutely right. Now it works. Thanks a lot for your help...

Best regards

-Yanghui
Back to top
View user's profile Send private message Send e-mail
JustFriend
PostPosted: Mon Jun 27, 2005 6:37 am    Post subject: Reply with quote

Novice

Joined: 30 May 2005
Posts: 22

Martin… thanks for your wonderful code for removing the painful blank xml tags. That was really wonderful.

I have modified a bit for removing the Carriage-Return (CR) and Line-Feed (LF) which also generates empty-tags in the output.

Please find below the code that I am using:


-- Recursive PROCEDURE:
CREATE PROCEDURE RemoveEmptyElements(INOUT Root REFERENCE)
BEGIN
DECLARE ClimbChildren BOOLEAN TRUE;
DECLARE CR CHAR CAST(CAST(X'0D' AS BLOB) AS CHAR CCSID InputRoot.MQMD.CodedCharSetId );
DECLARE LF CHAR CAST(CAST(X'0A' AS BLOB) AS CHAR CCSID InputRoot.MQMD.CodedCharSetId );

IF TRIM(Root) = '' THEN
DECLARE Elmnt REFERENCE TO Root;
DETACH Elmnt;
SET Elmnt = NULL;
SET ClimbChildren = FALSE;
END IF;

IF (POSITION(LF IN FIELDVALUE(Root)) > 0) AND (LENGTH(FIELDNAME(Root)) < 1 ) THEN
DECLARE Elmnt REFERENCE TO Root;
DETACH Elmnt;
SET Elmnt = NULL;
SET ClimbChildren = FALSE;
END IF;

IF (POSITION(CR IN FIELDVALUE(Root)) > 0) AND (LENGTH(FIELDNAME(Root)) < 1 ) THEN
DECLARE Elmnt REFERENCE TO Root;
DETACH Elmnt;
SET Elmnt = NULL;
SET ClimbChildren = FALSE;
END IF;

IF ClimbChildren THEN
DECLARE NxtSibl REFERENCE TO Root;
MOVE NxtSibl FIRSTCHILD;
WHILE LASTMOVE(NxtSibl) DO
DECLARE Child REFERENCE TO NxtSibl;
MOVE NxtSibl NEXTSIBLING;
CALL RemoveEmptyElements(Child);
END WHILE;
END IF;
END;



Please tell me if I am right else seeking your valuable advice.

Best Regards,
MOHD IQHBAL.
Back to top
View user's profile Send private message Yahoo Messenger MSN Messenger
martinrydman
PostPosted: Tue Jun 28, 2005 3:15 am    Post subject: Reply with quote

Centurion

Joined: 30 Jan 2004
Posts: 139
Location: Gothenburg, Sweden

Hi,

Seems OK, and if it works, well then there's no problem

/Martin
Back to top
View user's profile Send private message
x061294
PostPosted: Wed Jun 29, 2005 6:41 am    Post subject: Reply with quote

Acolyte

Joined: 05 Apr 2005
Posts: 62

I've tried this code, and several people have responded how it works, but, I can't get it to work. I'm running 5.0.4 of broker on Windows.

Here is the statements that I used to create the XML

Code:
Set OutputRoot.XML.A.B.C = InputRoot.XML.Customer.Name.FirstName;
Set OutputRoot.XML.A.B.D = InputRoot.XML.Customer.Name.Title;   
Set OutputRoot.XML.A.B.Error = InputRoot.XML.Customer.Name.Error;
CREATE LASTCHILD OF OutputRoot.XML.A.B.C NAME 'ERROR' VALUE InputRoot.XML.Customer.Name.FirstName.Error;

which generate the following XML

<A>
<B>
<C>
Fred
<ERROR></ERROR>
</C>
<D>Mr</D>
</B>
</A>

I then execute the code:

Code:
DECLARE OutMsg REFERENCE TO OutputRoot.XML;
CALL RemoveEmptyElements(OutMsg);
      
CREATE PROCEDURE RemoveEmptyElements(INOUT Root REFERENCE)
BEGIN
    DECLARE ClimbChildren BOOLEAN TRUE;

    IF TRIM(Root) = '' THEN
        DECLARE Elmnt REFERENCE TO Root;
       DETACH Elmnt;
       SET Elmnt = NULL;
       SET ClimbChildren = FALSE;
    END IF;       
       
    IF ClimbChildren THEN
      DECLARE NxtSibl REFERENCE TO Root;
       MOVE NxtSibl FIRSTCHILD;
      WHILE LASTMOVE(NxtSibl) DO
         DECLARE Child REFERENCE TO NxtSibl;
        MOVE NxtSibl NEXTSIBLING;
        CALL RemoveEmptyElements(Child);
       END WHILE;
    END IF;
END;    


and trace it through. The flow goes to the first if,
Code:
IF TRIM(Root) = '' THEN


which results in true, detaches and null's the whole tree, and ends. No matter what I do, the statement always results in true which means that i don't walk the tree.

2005-06-29 10:30:29.635307 5664 UserTrace BIP2539I: Node 'ABC_XML.Compute1': Finished evaluating expression 'TRIMBOTH(BOTH FROM Root) = ''' at (.ABC_XML_Compute1.RemoveEmptyElements, 6.19). This resolved to ''' = '''. The result was 'TRUE'.

Any ideas on why the trim of the root would come back as '' right out the bat?
Back to top
View user's profile Send private message
mverh
PostPosted: Wed Oct 26, 2005 12:50 pm    Post subject: Reply with quote

Voyager

Joined: 06 Mar 2002
Posts: 97

I need code like this...and like the last post by x061294 this code doesn't work for me either...since people posted it did work I am curious to know if it is a V2.1 versus V5 issue...in any case I am in the process of modifying it and wonder if anyone has as well and has a working copy for V5....thx...

Marc
Back to top
View user's profile Send private message
elvis_gn
PostPosted: Wed Oct 26, 2005 8:33 pm    Post subject: Reply with quote

Padawan

Joined: 08 Oct 2004
Posts: 1905
Location: Dubai

Hi guys,

From the first post, i feel that TonyD was just trying to see if the field is empty, and if yes then not get it in the Output itself.....

Instead on running a procedure for this and looping through every element to see the length etc, why not use COALESCE with NULL.....



Regards.
Back to top
View user's profile Send private message Send e-mail
JustFriend
PostPosted: Wed Oct 26, 2005 11:59 pm    Post subject: Reply with quote

Novice

Joined: 30 May 2005
Posts: 22

For everybody's benefit, we request you to post the ESQL.

Thank you
_________________
Best Regards,
Just Friend.
Back to top
View user's profile Send private message Yahoo Messenger MSN Messenger
mverh
PostPosted: Thu Oct 27, 2005 12:16 pm    Post subject: Reply with quote

Voyager

Joined: 06 Mar 2002
Posts: 97

Ok, I have got a fix to the code that works...kind of...

the new code looks like...

Code:
CREATE COMPUTE MODULE recursiveCode_Compute
   CREATE FUNCTION Main() RETURNS BOOLEAN
   BEGIN
      -- CALL CopyMessageHeaders();
      CALL CopyEntireMessage();
            
      DECLARE OutMsg REFERENCE TO OutputRoot.XML.[1];
      CALL RemoveEmptyElements(OutMsg);
      
      RETURN TRUE;
   END;
   
   
   
   -- Recursive PROCEDURE:
   CREATE PROCEDURE RemoveEmptyElements(INOUT inXML REFERENCE)
   BEGIN
      DECLARE ClimbChildren BOOLEAN TRUE;
      
      IF TRIM(inXML) = '' THEN
         DECLARE Elmnt REFERENCE TO inXML;
         DETACH Elmnt;
         SET Elmnt = NULL;
         SET ClimbChildren = FALSE;
      END IF;
      
      IF ClimbChildren THEN
         DECLARE NxtSibl REFERENCE TO inXML;
         MOVE NxtSibl FIRSTCHILD;
         WHILE LASTMOVE(NxtSibl) DO
            DECLARE Child REFERENCE TO NxtSibl;
            MOVE NxtSibl NEXTSIBLING;
            CALL RemoveEmptyElements(Child);
         END WHILE;
      END IF;
   END;
   
   CREATE PROCEDURE CopyMessageHeaders() BEGIN
      DECLARE I INTEGER 1;
      DECLARE J INTEGER CARDINALITY(InputRoot.*[]);
      WHILE I < J DO
         SET OutputRoot.*[I] = InputRoot.*[I];
         SET I = I + 1;
      END WHILE;
   END;
   
   CREATE PROCEDURE CopyEntireMessage() BEGIN
      SET OutputRoot = InputRoot;
   END;
END MODULE;


Note the
Code:
 
DECLARE OutMsg REFERENCE TO OutputRoot.XML.[1];


is what was changed.


What doesn't work is if you send in a message that looks like <A></A>...in this case the message ends up with no body and the MQPut fails. I suppose a check could be done to see if this is the case. Enjoy...
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic  Reply to topic Page 1 of 1

MQSeries.net Forum Index » WebSphere Message Broker (ACE) Support » Removing empty elements in output XML
Jump to:  



You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Protected by Anti-Spam ACP
 
 


Theme by Dustin Baccetti
Powered by phpBB © 2001, 2002 phpBB Group

Copyright © MQSeries.net. All rights reserved.