godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
86.59k stars 19.3k forks source link

XMLParser get_node_name only works on NODE_ELEMENTs #28768

Open Jummit opened 5 years ago

Jummit commented 5 years ago

Godot version: 3.1.1

Issue description: get_node_name doesn't work on any nodes other than NODE_ELEMENT and NODE_ELEMENT_END. Sometimes I want to get the name of a NODE_TEXT, which isn't possible. This is probably to avoid trying to get the names of NODE_NONE or maybe NODE_UNKNOWN. The docs state

Get the name of the current element node. This will raise an error if the current node type is not NODE_ELEMENT nor NODE_ELEMENT_END

Steps to reproduce: Create a new XMLParser, load in an xml file with the first element being a simple text node, call read() and then get_name(). Example text element:

<description>
    Vector3 is one of the core classes of the engine.
</description>

Workaround: Since the end of an element is always NODE_ELEMENT_END, you can get the name from that element.

grubmunch commented 4 years ago

this issue is still present in 3.2.1

timothyqiu commented 3 years ago

I'm a bit confused about "the name of a NODE_TEXT".

<description>
    Vector3 is one of the core classes of the engine.
</description>

This XML document contains only one XML element named "description" and its content is "Vector3 is one of the core classes of the engine.".

But IIRC, XMLParser works by breaking the document into nodes, not elements. It's three nodes here:

  1. NODE_ELEMENT, has name "description"
  2. NODE_TEXT, has data "Vector3 is one of the core classes of the engine."
  3. NODE_ELEMENT_END, has name "description"

the NODE_TEXT node does not have name.

rhyzue commented 3 years ago

Still an issue for 3.3.2 I'm making a visual novel type game and it's much easier to write (story) scripts in XML than json. It's really annoying that this doesn't work because I need to differentiate between different text nodes. For example...

<dialogue> The character is speaking and you can reply to her. </dialogue>
<choice id="1"> You can say this </choice> 
<choice id="2"> Or this </choice> 

While there are workarounds, such as encapsulating the choices in an element node, it clogs up the script making it harder to read. Please fix, I want my nice clean efficient scripts ;-;

timothyqiu commented 3 years ago

You can do that by adding three lines of code to the regular parser, like this:

var raw = """
<root>
<dialogue> The character is speaking and you can reply to her. </dialogue>
<choice id="1"> You can say this </choice>
<choice id="2"> Or this </choice>
</root>
"""

var parser = XMLParser.new()
parser.open_buffer(raw.to_utf8())

var current_element = ""  # 1
while parser.read() == OK:
    match parser.get_node_type():
        XMLParser.NODE_ELEMENT:  # 2
            current_element = parser.get_node_name()  # 3
        XMLParser.NODE_TEXT:
            printt(current_element, parser.get_node_data())

and it outputs

dialogue   The character is speaking and you can reply to her.
choice     You can say this
choice     Or this
rhyzue commented 3 years ago

You can do that by adding three lines of code to the regular parser, like this:

var raw = """
<root>
<dialogue> The character is speaking and you can reply to her. </dialogue>
<choice id="1"> You can say this </choice>
<choice id="2"> Or this </choice>
</root>
"""

var parser = XMLParser.new()
parser.open_buffer(raw.to_utf8())

var current_element = ""  # 1
while parser.read() == OK:
    match parser.get_node_type():
        XMLParser.NODE_ELEMENT:  # 2
            current_element = parser.get_node_name()  # 3
        XMLParser.NODE_TEXT:
            printt(current_element, parser.get_node_data())

and it outputs

dialogue   The character is speaking and you can reply to her.
choice     You can say this
choice     Or this

Ohh, it works! Looking at your comment regarding node structure, it makes sense. Maybe it should be mentioned in the docs though. Thanks!

MewPurPur commented 3 months ago

This has been documented since at least 4.1