Playmaker Forum

Bug Reporting => PlayMaker Bug Reporting => Topic started by: Padenlee on May 08, 2019, 01:13:47 PM

Title: Datamaker XPath "invalid token" when using name()
Post by: Padenlee on May 08, 2019, 01:13:47 PM
Hi awesome community!  8) I'm a veteran of Playmaker, but novice to DataMaker, I always created my own parsers by hand before.

I'm trying to get the XML node tag/name with the action Select Single Node using the XPath //buildings/*[1]/name()
This works when testing my XML and XPath on freeformatter.com (See attached image), but does not work when attempting it with Select Single Node action, I get an invalid token error in console.

Is the idea to put all the relevant information as attributes in nodes and not reference the node names directly? Is there a list of XPath commands that are supported by Datamaker? Am I trying to start my car with a honey glazed ham(inputs all wrong)?

-Thanks in advance for any info!
Title: Re: Datamaker XPath "invalid token" when using name()
Post by: djaydino on May 09, 2019, 04:39:56 AM
Hi.
You might want to use xmlToolbox (https://xmltoolbox.appspot.com/xpath_generator.html) instead.

To get the name, you would get this result :
Code: [Select]
/game/buildings/forge[@name="Forge"]@name
to set this up in the select single node action, you can place the line in the xpath query minus "@name"

Then add @name to store node properties and you can do this for the other ones as well (see image below)

(https://i.imgur.com/WsmQTprl.png)

You can also follow this tutorial :

Title: Re: Datamaker XPath "invalid token" when using name()
Post by: jeanfabre on May 17, 2019, 01:09:51 AM
Hi,

 yes, not all xpath commands are supported unfortunatly. if you still have trouble, send me the xml and I'll work out the query to get you up and running.

 Bye,

 Jean
Title: Re: Datamaker XPath "invalid token" when using name()
Post by: Padenlee on May 21, 2019, 12:39:33 PM
Thanks djaydino for your response, it really helped me understand that I was not missing something.

I'm always a little star struck when Jean responds to my posts #notworthy

I feel extremely versed in DataMaker now, I always try and learn everything I can about a thing before mentioning any changes because I understand the dev teams time is very valuable. Now that I know what I'm doing, I think fancy XPath commands would be a luxury but not needed at the moment. I do think a few simple changes to existing actions would provide the largest improvement to function, along with making DataMaker an even stronger element to every app I or anyone makes in the future.

Suggested changes to DataMaker:
Add "Node Name" field to the following actions because a developer can't loop through a list of nodes and get the node names. This prevents dynamic lists of child nodes and forces developers to know what the node name is beforehand (causing interdependencies in business logic) or do what I do and have every node have a @name="nodeName" attribute. This causes a lot of redundant copy and pasting values in the XML file and feels like I'm fighting the XML way, in so much as it makes node structure like this:

<node name="nodeName" value="1234"></node>

Rather than the simpler way:

<node>1234</node>.

You can always mix the two with:

<node name="nodeName">1234</node>

But this feels disjointed.


Add "Node Name" field to the following actions:
XML Get Next Node List Properties
XML Get Node Properties
XML Select Single Node
XML Create Node
XML Insert Node
XML Set Node Properties

If I could be so bold as to also suggest adding "In Memory" to the following actions:
XML Save In Proxy
XML Proxy Get XML As String

It's been a minute since I've suggested any changes that aren't bug reports, if there is a new fancy "Suggest Changes" process with Playmaker now I'd love to post there to support development structure.

Veni, vidi, vici with Playmaker!
Title: Re: Datamaker XPath "invalid token" when using name()
Post by: jeanfabre on May 22, 2019, 03:52:19 AM
Hi,

 Thanks for the kind words :)

if the following is tltr: update datamaker, you have now Name() as a property query
(https://i.imgur.com/v1Tu5HB.png)

----- now onto the explanation :)

I think you are mistaken with the structure and the content. It's not a good practice that your node represent the data itself, the node name is the structure of your data.

it doesn't take away this request and I agree it's useful, but I think you could end up in trouble down the road by doing so, it's not how xml was designed to be used. the data structure must be known, and the data itself should indicate what's coming next.

so it's perfectly fine and recommended to add attributes to define the content like you did, but it should not be the "name" of the node, but rather something specific to your data semantic meaning. if the node is a prop in your scene then you should have

<prop type="furniture>content expect to be formatted to describe a furniture</prop>

instead  of <node name="nodename"> which confuse structure and data.


let's take the example of a human holding a tool. you don't know what his holding, could be food, could be anything. One way would be to do like you did, creating a node inside the right hand node and get the name of the name to know what it is.

<hand><food>Apple</food></hand>

with the above, you need to tap into the structure itself mixing it up with the data itself in order to know what's going on.

but what if I create a generic prop node instead.

<hand><prop type="food">Apple</prop></hand>

this second approach is far more powerful and flexible both to represent data and to work with it for programming, it's powerfull because the structure is expected, a Hand can only have a Prop as a child node, and the content of the Prop node is known via its structural attribute type, which lets your program know what to expected inside that prop node. Likely it will be more detailed:

<hand>
 <prop type="food">
   <food>
    <name>Apple></name>
    <sort>Granny smith</sort>
   </food>
 </prop>
</hand>


Does that make sense? while I also agree that it doesn't help when you don't know what's coming up should you have not followed that structure paradigm I just explained. Html being the example, where within a div, you don't know what you will get. However, as I said earlier, you a re opening a can of worm with this approach even if it feels at first a very elegant one.

long story short, I have added this possibility right within xpath, allowing you to query the name of a node like this: "Name()" which is a valid xpath query.

for XML Save In Proxy and save xml as string, the proxy component itself has a "Store in memory: property, so you can use that. Is that not working on your end?

Please update it from the ecosystem, note that it's now distributed starting from 5.6, not 4.x anymore. and soon, 2017 will be the new starting point, Unity is going to move away from supporting 5.x in july.

Bye,

 Jean







Title: Re: Datamaker XPath "invalid token" when using name()
Post by: Padenlee on May 23, 2019, 03:39:28 PM
Fantastic adding name() functionality!

I totally get what you're saying about node structure and I agree 100%. I think the subtlety of our conversation is similar to arrays and hash tables. Technically two arrays are a hash table. Why use a hash table then? Basically, because of simplicity.

<item name="Iron Sword" sprite="ironSword" count="1">

Can now be

<ironSword>1</ironSword

This makes you use the machine name more than the display name. Also acts more like a node ID, though duplicates are likely
Using the Load Resources action to load the sprite based on node name and not a specific @sprite attribute.
Displaying the name would require string conversion or adding a name="Iron Sword", but I feel this is better for structure, where @name is only for displaying text on screen and I could change it to name="Rusty Iron Sword" all I want without breaking the backend logic when another FSM is trying to find /game/items/*[@name="Iron Sword"]. Instead the FSM looks for /game/items/ironsSword and finds it and displays "Rusty Iron Sword". This honestly is future proofing based on human nature to change what the player sees more than the backend. Also, translating into foreign languages would only need to focus on display text.

I think all three methods are needed for a strong ecosystem of development.

1. <ironSword>1</ironSword>
2. <ironSword attack="5" defense="2"></ironSword>
3. <item id="23486" name="Iron Sword" sprite="ironSword" count="1">


I'd suggest 1 for when you need to have a large list of nodes that are numeric focused, like an inventory: "<healingHerb>99</healingHerb>". 2 for equipped items where you can only have 1 item equipped but it has many attributes attack, defense, cost, etc. Using 3 for hyper specific structures - anything that would need a node ID, etc. I tend to steer away from complex structures in favor of development speed. I use a simple>detail>complex approach to my app structures, I try to use the simplest method of I can.

I hope this helps understand my thought process and reasoning behind node name importance.

Thanks again for the insanely fast update to DataMaker!

Here is the details about the Save To Proxy when using In Memory bug:
Title: Re: Datamaker XPath "invalid token" when using name()
Post by: Padenlee on May 23, 2019, 07:26:42 PM
For anyone in the future finding this thread, here is how you now implement this gloriously simple structure. For this example we'll be looping through an inventory XML after a shop has added items into the players inventory XML:

XML:
<inventory>
   <ironSword>1</ironSword>
   <redMushroom>2</redMushroom>
</inventory>

XML Select Nodes
-Source selection: However you have your XML stored
-xPath Query: /game/inventory/*
-Store Reference: Node List
-Found Event: Xml/Found
[ Get Inventory ] --transition-->[ Get Item Information ]
XML Get Next Node List Properties
Node List Reference: Node List
-Store Node Properties: 2
-Element 0
--Property: Name()
--Type: String
--Variable: sNode
-Element 1
--Property: sNode
--Type: Int
--Variable: iItemCount

Process information how you see fit, example:

Resources Load
-Asset Path: sNode
-Type: Object
-Store Asset: oSprite
Set Sprite
-GameObject: Specify Game Object: Inventory Item
-Sprite: oSprite

Note: You feed the node name you get from using Name() in Element 0 into the Property field of Element 1, this will get you the node value output into the Variable field.

So epicly dope!