What's the best way to convert form data to XML in javascript?



  • I have a program (a Dungeon Master helper app) that allows you to import and create your own creatures (among other things). Creating them on the tablet is...painful (no keyboard, tiny screen, etc).

    But you can import XML compendiums in a homegrown format, so...easy, right? Just write a simple UI form to take the data and shove it into XML.

    So I've (to learn electron/node/JS better) written a simple one-page electron app that does just that. Where I'm getting stuck is at the best (ie non-insane) way to map that input (in the form of <input> and <textarea> elements) into this particular XML format.

    Standard JSON -> XML libraries require you to write your JSON in a particularly odd way. Simple translation code I found doesn't let you map an array of elements into a bunch of repeated, identically-named XML elements[1].

    Am I going to have to do this by hand? Extract each element by id, grab its innerHTML (no attributes here, just text nodes) and manually generate the DOM elements[2]?

    [1] It expects something like

      <trait>
        <name>foo</name>
        <text>a bunch of text here</name>
        ...many more text lines possibly
      </trait>
     <trait>
        <name>bar</name>
        <text>a bunch of text here</name>
        ...many more text lines possibly
      </trait>
      ...
    

    [2] I plan to use the DOM (xml form) API, not hand-write the tags by concatenating strings.


  • ♿ (Parody)

    Is the XML schema complicated?

    If it's just a bunch of <trait> elements like you outlined, using a "conversion library" seems overkill.

    Just loop over your inputs and build something using DOMParser or even string concatenation.



  • @apapadimoulis said in What's the best way to convert form data to XML in javascript?:

    Is the XML schema complicated?

    If it's just a bunch of <trait> elements like you outlined, using a "conversion library" seems overkill.

    Just loop over your inputs and build something using DOMParser or even string concatenation.

    It's not particularly complicated, but it's...well...here's a simple example.

    <monster>
    		<name>Abjurer</name>
    		<size>M</size>
    		<type>humanoid (any race), Volo's Guide</type>
    		<alignment>any alignment</alignment>
    		<ac>12 (15 with mage armor)</ac>
    		<hp>84 (13d8+26)</hp>
    		<speed>30 ft.</speed>
    		<str>9</str><dex>14</dex><con>14</con><int>18</int><wis>12</wis><cha>11</cha>
    		<save>Int +8, Wis +5</save>
    		<skill>Arcana +8, History +8</skill>
    		<resist />
    		<vulnerable />
    		<immune />
    		<conditionImmune />
    		<senses />
    		<passive>11</passive>
    		<languages>any four languages</languages>
    		<cr>9</cr>
    		<trait>
    			<name>Spellcasting</name>
    			<text>The abjurer is a 13th-level spellcaster. Its spellcasting ability is Intelligence (spell save DC 16, +8 to hit with spell attacks). The abjurer has the following wizard spells prepared:</text>
    			<text />
    			<text>Cantrips (at will): blade ward. dancing lights, mending, message, ray of frost</text>
    			<text />
    			<text>1st level {4 slots): alarm*, mage armor, magic missile, shield*</text>
    			<text />
    			<text>2nd level (3 slots): arcane lock*, invisibility</text>
    			<text />
    			<text>3rd level (3 slots): counterspell*, dispel magic*, fireball</text>
    			<text />
    			<text>4th level (3 slots): banishment*, stoneskin*</text>
    			<text />
    			<text>5th level (2 slots): cone of cold, wall of force</text>
    			<text />
    			<text>6th level (1 slot): flesh to stone, globe of invulnerability*</text>
    			<text />
    			<text>7th level (1 slot): symbol* teleport</text>
    			<text />
    			<text>*Abjuration spell of 1st level or higher</text>
    		</trait>
    		<trait>
    			<name>Arcane Ward</name>
    			<text>The abjurer has a magical ward that has 30 hit points. Whenever the abjurer takes damage, the ward takes the damage instead. If the ward is reduced to 0 hit points, the abjurer takes any remaining damage. When the abjurer casts an . abjuration spell of 1st level or higher, the ward regains a number of hit points equal to twice the level of the spell.</text>
    		</trait>
    		<action>
    			<name>Quarterstaff</name>
    			<text>Melee Weapon Attack: +3 to hit, reach 5 ft., one target. Hit: 2 (1d6-l) bludgeoning damage, or 3 (1d8-l) bludgeoning damage if used with two hands.</text>
    			<attack>Quarterstaff|3|1d6-l</attack>
    			<attack>Two Handed|3|1d8-1</attack>
    		</action>
    		<spells>blade ward, dancing lights, mending, message, ray of frost, alarm, mage armor, magic missile, shield, arcane lock, invisibility, counterspell, dispel magic, fireball, banishment, stoneskin, cone of cold, wall of force, flesh to stone, globe of invulnerability, symbol teleport</spells>
    		<slots>4,3,3,3,2,1,1,0,0</slots>
    	</monster>
    

    where <trait>, <action>, and legendary (not present in this example) can appear 0...N times and the others are optional if empty, except for a few.

    I thought about simply making a mapping dictionary between the tag ids and the tags, but the 0...N nature was tripping me up (since the tag ids are currently trait0, ..., traitN (and similarly for action and legendary.


  • ♿ (Parody)

    @Benjamin-Hall it doesn't look all that complicated, but there's a lot of fields and I suspect they all have different shapes of values. Maybe one input field will be a drop down, the other will be free text, the other is a tag text box? And so on.

    You can't really escape the fact that there are a lot of fields. And that each field is a little different.

    The more you try to generalize this, the more code and complexity it will be, and worse, the more difficult the user experience will be.

    Chances are, you don't add fields that often.



  • @apapadimoulis said in What's the best way to convert form data to XML in javascript?:

    @Benjamin-Hall it doesn't look all that complicated, but there's a lot of fields and I suspect they all have different shapes of values. Maybe one input field will be a drop down, the other will be free text, the other is a tag text box? And so on.

    You can't really escape the fact that there are a lot of fields. And that each field is a little different.

    The more you try to generalize this, the more code and complexity it will be, and worse, the more difficult the user experience will be.

    Chances are, you don't add fields that often.

    Fortunately, only one of these is anything other than just unstructured[1] text (the size field is one a drop down). The rest are just plain text that I'm not (at this point) worrying about breaking down further.

    I'm prototyping a "walk the input elements, create nodes, stuff them into the XML document" strategy...

    [1] well, there's structure. Those <attack></attack> values have meaning, as do several others. But I'm not going fancy. They're just <input type="text"> elements or at most <textarea> elements for the <text> fields.



  • As an alternative to parsing the id of each element to get the xml tag, you could put it in a data- attribute on the element



  • And that worked. With a few derps along the way (document.querySelectorAll(selector) wants actual CSS selectors, not just class names) and the usual "oh wait, you didn't save the document before testing it" derps. But it works, at least for simple things.

    Yay.

    Thanks @apapadimoulis and @hungrier -- both of you gave me pieces of the solution and it wasn't that bad.


  • ♿ (Parody)

    Oh oh, what about making an XSLT that transforms your XML into XHTML, and then another XSLT that transforms it right back to XML! This way no JavaScript is needed.

    • except all the javascript required to do the horrendous transformations and hacks to get it working

  • Considered Harmful

    There must be some way to cram WASM in here somewhere.



  • @pie_flavor said in What's the best way to convert form data to XML in javascript?:

    There must be some way to cram WASM in here somewhere.

    Bonus points for compiling at least 2 languages not made for the web to WASM and then trying to link the result together.


  • BINNED

    @dfdub said in What's the best way to convert form data to XML in javascript?:

    @pie_flavor said in What's the best way to convert form data to XML in javascript?:

    There must be some way to cram WASM in here somewhere.

    Bonus points for compiling at least 2 languages not made for the web to WASM and then trying to link the result together.

    Let's throw some dice... 🎲 🎲
    and it's going to be...

    FORTRAN and Haskell.



  • @topspin I'm more partial to Brainfuck.


  • ♿ (Parody)

    Where's the database? Can we at least get MongoDB in here?



  • @topspin said in What's the best way to convert form data to XML in javascript?:

    FORTRAN [in topic about XML]

    /me has immediate PTSD.


  • Discourse touched me in a no-no place

    @Benjamin-Hall said in What's the best way to convert form data to XML in javascript?:

      <ac>12 (15 with mage armor)</ac>
      <hp>84 (13d8+26)</hp>
      <speed>30 ft.</speed>
    
      <save>Int +8, Wis +5</save>
      <skill>Arcana +8, History +8</skill>
    
      	<attack>Quarterstaff|3|1d6-l</attack>
      	<attack>Two Handed|3|1d8-1</attack>
    
      <slots>4,3,3,3,2,1,1,0,0</slots>
    

    Speaking with my general XML schema design hat on, these are the only really WTF-y bits as they look like structured fields rather than freeform text. At least in theory, these should all be represented as something more complex (so that software could read it and act on it without having to, say, run it through regexps to parse it further). It's especially the presence of separator characters that has a nasty XML smell…



  • @dkf oh absolutely. But it's the schema the program expects.

    And except for the attack one, almost exactly how that data is displayed. Only the attack one actually gets parsed further. Edit: and the slots one.


  • Discourse touched me in a no-no place

    @Benjamin-Hall The slots one looks like it might be as well. (It appears to match up with stuff from the spellcasting traits, but that's obviously text for people as it describes stuff that you'd probably end up writing a chunk of code for to implement in software.)



  • @dkf yeah, I edited that one in. It gets broken into 9 separate elements. In fact, on the display end, that one gets moved around the most. The attack one gets shoved into one box. And for my use is really optional, since it's there to enable auto rolling of attacks and damage and I don't use that feature.


Log in to reply