XMLPORT:Skip Empty Tags

pgroppusopgroppuso Member Posts: 2
Good Morning.
does anyone know how to skip empty tags when exporting with a XmlPort?
I tryed to do that setting the MinOccurs property of the element to zero but does'nt work.
It's a great problem form me because my commitment don't accept empty tags.
Can somebody help me?
Thanks for all.

Comments

  • bluesky29bluesky29 Member Posts: 29
    Hi,

    i had the same problem. solved it like that:


    DeleteEmptyXMLNodes(VAR XMLNode : Automation "'Microsoft XML, v3.0'.IXMLDOMNode")
    IF XMLNode.nodeTypeString = 'element' THEN BEGIN
    IF (XMLNode.hasChildNodes = FALSE) THEN BEGIN
    IF (XMLNode.xml = '<' + XMLNode.nodeName + '/>') THEN
    XMLNode := XMLNode.parentNode.removeChild(XMLNode)
    END ELSE BEGIN
    XMLDomNodeList := XMLNode.childNodes;
    FOR i := 1 TO XMLDomNodeList.length DO BEGIN
    XMLChildNode :=XMLDomNodeList.nextNode();
    DeleteEmptyXMLNodes(XMLChildNode);
    END;
    END;
    END;

    following local variables:
    XMLChildNode Automation 'Microsoft XML, v3.0'.IXMLDOMNode
    XMLDomNodeList Automation 'Microsoft XML, v3.0'.IXMLDOMNodeList
    i Integer

    you can use it with an existing xml-document like that:

    CurrNode Automation 'Microsoft XML, v3.0'.IXMLDOMNode

    CurrNode := XMLDOMDocument.documentElement;
    DeleteEmptyXMLNodes(CurrNode);

    hope this helps. :D
  • DenSterDenSter Member Posts: 8,307
    Cool, that should go into the Tips and Tricks area. :mrgreen:
  • snyktpsnyktp Member Posts: 75
    Hello

    I am trying this but I dont understand what taht is ;CurrNode := XMLDOMDocument.documentElement;

    Thank you
  • DenSterDenSter Member Posts: 8,307
    The documentelement is the root element of the XML document. CurrNode is the node that you are currently looking at. That code puts the root element of the XML document into the CurrNode variable
  • axxionaxxion Member Posts: 1
    Hi All,

    I followed exactly these instructions.

    In the XML port, at the OnPostXMLport() trigger I call:

    CurrNode := XMLDOMDocument.documentElement;
    DeleteEmptyXMLNodes(CurrNode);

    The function DeleteEmptyXMLNodes(CurrNode); is also in the XML port.

    The XML port compiles well but during running I get the error (translated):

    This message is for C/AL programmers:

    Could not create a working copy of the Automation variable.
    You can create a working copy by creating a variable or applying.

    I reinstalled the client, NAV 4.0 SP3 native, with all options.
    I reinstalled MSXML 3.0 SP7.
    Tried also XML 4.0 and 6.0 but no improvement. ](*,)
    Any suggestions?
  • InfoWisslerInfoWissler Member Posts: 10
    I used the code provided by bluesky29 for two years (was used only in the beginning of every year but very often then) and now I have the same problem as axxion (Post above).

    I tried the code with the help of following builds:

    NAV-Build SQL-Build Works
    32275 (R2) 10.5…… (R2) No
    31671 10.5…. (R2) No
    32275 (R2) 10.0…. No
    31671 10.0…. Yes

    My theory was that it is a problem with some Update in late 2012, but if this problem already occurred in 2007 (axxion), it seems to be something different. Has anybody any ideas? I doublechecked the NAV objects in the above databases.

    (I do not use the code directly in an xmlPort, but I save a xmlport-Export as a BLOB in a table; later I load the BLOB in a xmldom Document - Variable; after that, I go on with the proposed code)

    edit: okay the reason has to be that I mess up my BLOB in my table somehow, because it only fails when I try to process the BLOB more than once.
  • AlkroAlkro Member Posts: 115
    bluesky29 wrote:
    DeleteEmptyXMLNodes(VAR XMLNode : Automation "'Microsoft XML, v3.0'.IXMLDOMNode")
    IF XMLNode.nodeTypeString = 'element' THEN BEGIN
    IF (XMLNode.hasChildNodes = FALSE) THEN BEGIN
    IF (XMLNode.xml = '<' + XMLNode.nodeName + '/>') THEN
    XMLNode := XMLNode.parentNode.removeChild(XMLNode)
    END ELSE BEGIN
    XMLDomNodeList := XMLNode.childNodes;
    FOR i := 1 TO XMLDomNodeList.length DO BEGIN
    XMLChildNode :=XMLDomNodeList.nextNode();
    DeleteEmptyXMLNodes(XMLChildNode);
    END;
    END;
    END;
    I tried this code but the result of .xml file was:
    <PstlAdr> 
        <StrtNm>STREET, 1</StrtNm>
        <PstCd>01234</PstCd>
        <TwnNm>TOWN</TwnNm>
        <Ctry/>
    </PstlAdr>
    
    See <Ctry/> Node... Strange!!!

    How can i skip Empty Nodes, and how a particular Node, for example only "Ctry" empty nodes. I suppose asking about XMLNode.nodeName = 'Ctry' but i have same result...

    Actually result is:
    <Cdtr>
       <Nm>NAME</Nm>
       <PstlAdr>
          <TwnNm/>
       </PstlAdr>
    </Cdtr>
    

    But i need this format:
    <Cdtr>
       <Nm>NAME</Nm>
       <PstlAdr>
       </PstlAdr>
    </Cdtr>
    

    :roll:

    BR
  • jordi79jordi79 Member Posts: 275
    Hi,

    I am trying to use this function to remove empty XML Tags on NAV2013. So I have changed everything from automation to DotNet. But I am facing a problem whereby I cannot parse the XMLNode to the function DeleteEmptyXMLNodes().

    Error Message is:

    Microsoft Dynamics NAV
    A DotNet variable has not been instantiated. Attempting to call MSXML.IXMLDOMNode.nodeTypeString in Report SI: XML Invoice Export: DeleteEmptyXMLNodes
    OK

    Main Body CU...
    XMLDomDocument := XMLDomConstructor.DOMDocumentClass;
    XMLDomDocument.loadXML(ServerFileName);
    CurrNode := XMLDomDocument.documentElement;
    
    DeleteEmptyXMLNodes(CurrNode);
    XMLDomDocument.save(ServerFileName);
    

    DeleteEmptyXMLNodes function...
    DeleteEmptyXMLNodes(VAR XMLNode : DotNet "MSXML.IXMLDOMNode")
    IF XMLNode.nodeTypeString = 'element' THEN BEGIN 
      IF (XMLNode.hasChildNodes = FALSE) THEN BEGIN 
        IF (XMLNode.xml = '<' + XMLNode.nodeName + '/>') THEN 
          XMLNode := XMLNode.parentNode.removeChild(XMLNode) 
        ELSE BEGIN 
          XMLDomNodeList := XMLNode.childNodes; 
          FOR i := 1 TO XMLDomNodeList.length DO BEGIN 
            XMLChildNode :=XMLDomNodeList.nextNode(); 
            DeleteEmptyXMLNodes(XMLChildNode); 
          END; 
        END;
      END; 
    END;
    
  • hitt123hitt123 Member Posts: 7
    edited 2020-12-10
    The easy way is to use CurrXMLport.skip insinde the Export::OnBeforePassVariable() trigger. If MyNode = '' then CurrXmlPort.Skip and the node is not created.
  • weneedweneed Member Posts: 82
    hitt123 wrote: »
    The easy way is to use CurrXMLport.skip insinde the Export::OnBeforePassVariable() trigger. If MyNode = '' then CurrXmlPort.Skip and the node is not created.
    This work great but not with tableelement. For tableelement there is not OnBeforePassVariable trigger.
    There is a work around? I need a solution for SaaS..
Sign In or Register to comment.