bmx-ng / brl.mod

BlitzMax Runtime Libraries, for BlitzMax NG.
12 stars 12 forks source link

[brl.xml] node.GetContent() returns initially set value #153

Open GWRon opened 5 years ago

GWRon commented 5 years ago

When using node.GetContent() after node.SetContent("test") the result is what was set as content on node creation (so eg when parsing an XML file).

Adjusted sample (doc/txmldoc_savefile.bmx):

SuperStrict

Framework brl.xml
Import BRL.StandardIO

' Create a new document
Local doc:TxmlDoc = TxmlDoc.newDoc("1.0")

If doc Then

    ' create a test stream
    Local stream:TTestStream = TTestStream.Create()

    ' create a new node, initially not attached to the document
    Local root:TxmlNode = TxmlNode.newNode("root")

    ' set the node as the document root node
    doc.setRootElement(root)

    local n:TxmlNode = root.addChild("things", "some stuff")
    n.SetContent("other stuff")
    print "content: " + n.GetContent()

    ' output the document to a file
    doc.saveFile("testfile.xml")

    ' output the document to a stream
    doc.saveFile(stream)

    ' output the document to console
    doc.saveFile("-")

    doc.Free()
End If

Type TTestStream Extends TStream

    Function Create:TTestStream( )
        Return New TTestStream
    End Function

    Method Write:Long( buf:Byte Ptr, count:Long )

        Print "outputing..."
        Print String.FromBytes( buf, Int(count) )

        Return count
    End Method

End Type

output:

content:
outputing...
<?xml version="1.0" encoding="utf-8"?><root><things>other stuff</things></root>
<?xml version="1.0" encoding="utf-8"?><root><things>other stuff</things></root>

As you see the GetContent() call returns the initial value (an empty string) while the final output contains the freshly set content.

GWRon commented 5 years ago

If I understood SetContent and AddContent right then the first removes all text elements from a node first and adds the content afterwards while the second just adds the content. Both call mxmlNewText.

The function mxmlNewText() in mxml-node.c is just adding a new text node to the parental node and then sets the text/value of this text element - but it does not seem to update the content of the parental node.

The GetContent() method utilizes mxmlGetOpaque which returns the node's value (not the one of text elements added to it).

GWRon commented 5 years ago

The content was refreshed when not using mxmlNewText but mxmlNewOpaque:

glue.c

//OLD
void bmx_mxmlSetContent(mxml_node_t * node, BBString * content) {
    mxml_node_t * child = mxmlGetFirstChild(node);
    while (child != NULL) {
        mxml_node_t * txt = NULL;
        if (mxmlGetType(child) == MXML_TEXT) {
            txt = child;
        }
        child = mxmlGetNextSibling(child);
        if (txt) {
            mxmlDelete(txt);
        }
    }
    char * c = bbStringToUTF8String(content);
    mxmlNewText(node, 0, c);
    bbMemFree(c);
}

//NEW
void bmx_mxmlSetContent(mxml_node_t * node, BBString * content) {
    mxml_node_t * child = mxmlGetFirstChild(node);
    while (child != NULL) {
        mxml_node_t * txt = NULL;
        txt = child;
        child = mxmlGetNextSibling(child);

        mxmlDelete(txt);
    }
    char * c = bbStringToUTF8String(content);
    mxmlNewOpaque(node, c);
    bbMemFree(c);
}

//OLD
void bmx_mxmlAddContent(mxml_node_t * node, BBString * content) {
    char * c = bbStringToUTF8String(content);
    mxmlNewText(node, 0, c);
    bbMemFree(c);
}

//NEW
void bmx_mxmlAddContent(mxml_node_t * node, BBString * content) {
    char * c = bbStringToUTF8String(content);
    mxmlNewOpaque(node, c);
    bbMemFree(c);
}

But I am not sure yet what impact such a change would have to other functionality.

The "NEW" SetContent() removes any child node for now (limiting to opaque and text nodes only somehow missed the previous "text node" or whatever contained the previous textual content of that node).