Al: [BUG?]: foreach XmlNodeList the XmlNode from SelectSingleNode is not allocating correctly

Created on 14 Mar 2019  Â·  4Comments  Â·  Source: microsoft/AL

Describe the bug

I am calling a web service that returns the following XML:

<content>
    <read refname="accountquery" responsestatus="success">
       <activeaccounts>
         <id>ae4e36fe-ff19-4587-96ea-cdb7770efa32</id>
         <name>First Credit Account</name>
         <platformtype.name>Credit Card</platformtype.name>
       </activeaccounts>
       <activeaccounts>
         <id>75a0218f-e111-4b4a-9689-db1b5186b3b6</id>
         <name>Second Credit Account</name>
         <platformtype.name>Credit Card</platformtype.name>
       </activeaccounts>
    </read>
</content>

I have the following local variables:

CurrentMessage: Text;
LocalXmlDocument: XmlDocument;
LocalNode: XmlNode;
LocalValueNode: XmlNode;
LocalXmlElement: XmlElement;
LocalNodeList: XmlNodeList;

What is happening is the first iteration processes just fine, but on the second iteration of the foreach is acting strange.
The LocalNode appears to allocate correctly, but the LocalNode.SelectSingleNode('//id', LocalValueNode) is grabbing the previous value of LocalNode for some reason.

To Reproduce
Steps and/or AL code to reproduce the behavior:

_I edited this to be a complete code block for execution._

```
trigger OnOpenPage();
var
XmlString: Text;
Doc: XmlDocument;
Node: XmlNode;
NodeList: XmlNodeList;
NewNode: XmlNode;
Options: XmlReadOptions;
Result: Text;
begin
Options.PreserveWhitespace := true;

    XmlString := '<content><read refname="accountquery" responsestatus="success"><activeaccounts><id>ae4e36fe-ff19-4587-96ea-cdb7770efa32</id><name>First Credit Account</name><platformtype.name>Credit Card</platformtype.name></activeaccounts><activeaccounts><id>75a0218f-e111-4b4a-9689-db1b5186b3b6</id><name>Second Credit Account</name><platformtype.name>Credit Card</platformtype.name></activeaccounts></read></content>';
    XmlDocument.ReadFrom(XmlString, Options, Doc);

    Doc.SelectNodes('//read[@refname="accountquery"]//activeaccounts', NodeList);

    if NodeList.Count() > 0
    then begin
        foreach Node in NodeList do begin
            Node.SelectSingleNode('//id', NewNode);
            Message(Node.AsXmlElement.InnerText);
            Message(NewNode.AsXmlElement.InnerText);
        end;
    end
    else begin
        Message('There were no accounts setup.')
    end;
end;

```

Expected behavior
The iteration should be setting LocalValueNode (XmlNode) to 75a0218f-e111-4b4a-9689-db1b5186b3b6 on the second iteration of the foreach LocalNodeList (XmlNodeList).

Screenshots

If applicable, add screenshots to help explain your problem.

Iteration 1 - LocalNode WriteTo Text

iteration-1-LocalNode

Iteration 1 - LocalValueNode WriteTo Text

iteration-1-LocalValueNode

Iteration 1 - LocalXmlElement InnerText

iteration-1-LocalXmlElement

Iteration 2 - LocalNode WriteTo Text

iteration-2-LocalNode

Iteration 2 - LocalValueNode WriteTo Text

iteration-2-LocalValueNode

Iteration 2 - LocalXmlElement InnerText

iteration-2-LocalXmlElement

Versions:

  • AL Language: 2.1.79379
  • Business Central: US Dynamics NAV 13.3 (29060)
bug platform-api xml

Most helpful comment

Indeed it's working : use ./ItemID/ID for find the node in the current Line.

All 4 comments

Hey @kalberes , I appreciate the labeling of the bug. Is there any updates by chance on this issue? We will be going to the Microsoft Directions Event in Early May (bought a booth!) and hoping we can convert our code from C/AL in time! Thank you~

Hi,
I found the same issue with this code in April '19 CU1 : Line is always giving the value of the first node(Line) only...

        XmlDoc.SelectNodes('//ShipmentItem', Lines);
        if Lines.Count > 0 then begin
            foreach Line in Lines do begin

                Line.SelectSingleNode('//ItemID/ID', XmlSubNode);
                ItemID := XmlSubNode.AsXmlElement().InnerText;

                Line.SelectSingleNode('//ShippedQuantity', XmlSubNode);
                ShippedQty := XmlSubNode.AsXmlElement().InnerText;

                Line.SelectSingleNode('//LineNumber', XmlSubNode);
                LineNumber := XmlSubNode.AsXmlElement().InnerText;

                message('Line\Item ID = %1\Shipped Qty = %2\Line Number = %3',
                    ItemID,
                    ShippedQty,
                    LineNumber)
            end;
        end;

Indeed it's working : use ./ItemID/ID for find the node in the current Line.

Replacing the "/" or "//" at the start of each XPath string with the context item expression "." followed by the "/" or "//" did the trick. Glad I found your post.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RonKoppelaar picture RonKoppelaar  Â·  3Comments

RedFoxUA picture RedFoxUA  Â·  3Comments

ThomasBrodkorb picture ThomasBrodkorb  Â·  3Comments

dkatson picture dkatson  Â·  3Comments

worldofthenavcraft picture worldofthenavcraft  Â·  3Comments