Can an HTML form be backed by an XML document? - javascript

Can an HTML form be bound to an XML document?
To give some context, Adobe XFA forms are XML documents created for purpose of rendering as a PDF form. They support XML bindings very similar to what I am looking for, but I'm not aware of anything similar in HTML forms and seeking suggestions.
An XFA form can also define bindings to an XML document that are bound to its form fields. It is not necessary for a schema to be defined -
the form can be merged with XML data or it can generate XML data based on the bindings specified in the form.
Example form definition:
<subform layout="tb">
<bind match="dataRef" ref="$.doc" />
<field w="0.5in">
<bind match="none" />
<ui>
<button />
</ui>
<caption>
<value>Add</value>
</caption>
<event activity="click" name="event__click">
<script contentType="application/x-javascript">
this.resolveNode("itemList").instanceManager.addInstance();
</script>
<event>
</field>
<subform layout="tb" name="itemList">
<bind match="dataRef" ref="$.item[*]">
<occur min="1" max="-1" />
<field w="2in">
<bind match="dataRef" ref="$.name" />
<ui>
<textEdit />
</ui>
<caption>
<value>Name</value>
</caption>
</field>
</subform>
</subform>
If the form was rendered with no data, it would appear similar to:
If the form was merged with the following input data:
<doc>
<item>
<name>item1</name>
</item>
<item>
<name>item2</name>
</item>
<item>
<name>item3</name>
</item>
</doc>
It would render similar to:
As you may notice in the form defintion code, Adobe XFA form is using its own XML language and expression syntax called SOM expressions. The first binding $.doc is binding to the top-level root node name doc.
The next binding $.item[*] is nested with the subform element and is relative to the $.doc binding.
The subform element is a container, similar to an HTML div element.
The subform is bound to item elements under the root doc element. the [*] syntax means that the subform will repeat itself for each item element in the xml document.
The occur element within the the subform element further qualifies how many instances can occur. The min=1 means that even if there are no item elements in the data merged into the form, it will automatically generate one. The max=-1 means there is no limit on the number of item instances.
The field element is bound to $.name. This means its value will update (or create) a name element under the current item.
The 'Add' button in the form creates new instances, Adobe Reader has a built-in Javascript engine and its own API to manage instances of the form that are persisted back to the XML data bound to the form.
Of course, the XML data can also be extracted from a saved PDF form.
There are many more capabilities in XFA forms such as conditional bindings, but I'm curious if something along these lines exists in HTML forms, perhaps some library that can link a form to an XML document and target them in a similar way.
XPATH would be ideal instead of the Adobe SOM expression syntax. Also, it would be ideal to have the XML posted from the form rather than name / value pairs that HTML forms would do by default.

There are many ways to convert XML into an HTML form. This question sounds an awful lot like a tool recommendation, so the only thing to do is list options:
Method 1:
This site walks the user through pasting an XML document, and then turns it into a form. It's pretty outdated, since the last change log was in 2006.
http://www.datamech.com/XMLForm/
Method 2:
You can write the script yourself, by converting XML > JSON then JSON > HTMLForm.
Converting the XML into JSON tools:
xml-js (NPM module)
xml2json (more popular, but has issues installing in Windows)
Blog tutorial (hand-made code)
Converting JSON into form tools:
json-forms (This might need you to follow a specific schema.)
Write the code yourself!

I'm guessing that what you're looking for is XSLT. This lets you transform a well-formed document of one kind into another. If this is what you want, there's a good answer here already.

In case other people stumble across this same question, you can get to exactly what you are looking for (creating html from xml documents) using xslt.
Think of this lonely post as your jumping off point to xslt. If you've never dealt with it before, it can be a little hard to digest. Fear not. Every journey begins with the first step. (etc. etc.)
Start with xml, and some idea of the html you want to create
So - for your example XML:
<doc>
<item name="Item1" />
<item name="Item2" />
<item name="Item3" />
</doc>
Let's assume you want to create a fairly simple HTML snippit:
<form class="tb">
<div><a class="btn btn-primary">Add</a></div>
<ul>
<li><label>Name</label><input type="text" class="form-control" value="Item1" /></li>
<li><label>Name</label><input type="text" class="form-control" value="Item2" /></li>
<li><label>Name</label><input type="text" class="form-control" value="Item3" /></li>
</ul>
</form>
Next, build your Xslt
There's some work at the beginning, and some syntax to learn. But, if we cut to the chase, this is the xslt that you'll end up with. It's just text. Just another file that you can hard code, embed, store in a file, grab from a url, etc.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" />
<xsl:template match="doc">
<form class="tb">
<div><a class="btn btn-primary">Add</a></div>
<ul>
<xsl:for-each select="item">
<li><label>Name</label><input type="text" class="form-control" value="<xsl:value-of select="#name"/>" /></li>
</xsl:for-each>
<xsl:if test="count(item)=0">
<li><label>Name</label><input type="text" class="form-control" value="" /></li>
</xsl:if>
</ul>
</form>
</xsl:template>
A few Xslt Notes
As you can see from the above, you setup a BASE document node to loop through with the <xsl:template match="doc"> tag. If your xml document has a doc node, then the html within the template is included. If there isn't a doc node, then it's skipped.
You can break out your xslt into different templates - and include them in the main template as well. It's pretty cool.
In the example above, we loop through your item nodes with an <xsl:for-each> tag, and we even have an "alternate" html which gets displayed if there are ZERO item tags (that's the empty input tag surrounded by
<xsl:if test="count(item)=0">).
There are some really great xslt references out there, but I like the one from Microsoft because I can use the c# code below to get html from a specific xslt tempate and my xml doc.
Finally, put it all together
Once you have your xml (above) and your xslt (also above), you can use them both to generate a string of html that is as long and complicated as you'd like. This is an almost verbatim copy of the method we use to generate massive mortgage contracts from xslt and really complex xml documents. I swear - it's lightning quick, and produces thousands of pages of html every day for us.
private string GetHtmlFromXslt(string xml, string xslt) {
XslCompiledTransform transform = new XslCompiledTransform();
using (XmlReader reader = XmlReader.Create(new StringReader(xslt))) {
transform.Load(reader);
}
StringWriter results = new StringWriter();
using (XmlReader reader = XmlReader.Create(new StringReader(xml))) {
transform.Transform(reader, null, results);
}
return results.ToString();
}
This is a .net core project file, referencing just System.Xml and System.Xml.Xsl - both of which are standard in System.Xml.
C-sharp!? Blech! Ach! The OP said JAVASCRIPT. Jeez...
I know you are a javascript guy. There are tools to do exactly the same thing (exactly) here and here.
I just haven't used those libraries because all of our xml is (a) private and (b) located on servers. But - I took a look at the code and they both follow the same approach -- one xml file and one xslt file, married with about 8-10 lines of actual code and producing a lovely html baby.
So. That's it. No tools. No third party plugins. No crazy json stuff.
Good luck! Can't wait to see what you crazy-kids create!

Related

Passing/exposing VXML Application root document variables to JSP

I need to have variables that are defined in my VXML application root document, which other documents modify, available to the JSP/EL pages. The idea here is that based on the value of these variable I can add logic to the JSP to render different blocks of VXML back to the IVR browser.
What I have tried so far does not generate any errors. It simply does not render the expected block of VXML code within the EL. My guess is that I am not de-referencing them correctly in EL.
Below is some of what I have tried.
root.vxml doc has
..
<var name="promptRetries" expr="''" />
...
start.jsp:
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml" application="/root.vxml" >
....
<assign name="application.promptRetries" expr="'3'" />
.....
<block>
<submit next="${pageContext.request.contextPath}/nextdoc.jsp" />
</block>
nextdoc.jsp
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml" application="/root.xml" >
....
<!-- at this point I can print and see the value of 3 for promptRetries -->
<!-- How can I expose this to JSP to accomplish something like the code below
I have used .equals() and other forms in the EL expression with no luck.
-->
<c:if test="${(application.promptRetries eq 1)} ">
<!-- Setting prompts for 1 retry -->
<catch event="noinput undefined" count="1" >
<audio expr="curPrompt2"/>
<log expr="buildLogStr(ibmCallId, documentName,frmName ,blkName,
'event=noinput count=1 reprompt', '')" />
</catch>
</c:if>
...
....
When developing VoiceXML applications in JSP, you need to be aware that there are two execution spaces. First, the Java server that generates the VoiceXML. Second, the VoiceXML Browser that executes it.
You already have an example of passing data from JSP to VoiceXML with the ${variable_name} syntax. To pass data from VoiceXML to JSP, you need to explicitly list the variables to send in the submit element:
<submit next="${pageContext.request.contextPath}/nextdoc.jsp" namelist="promptRetries"/>
And then in your second JSP page, use
request.getParameter("promptRetries")
to access the variable sent from the browser.

making links clickable while pushing the data into templates

I am taking inputs from user, then adding links for mentioned users and then passing the same in the template
Input: hello #ds
String after adding links -
"#<a class="tweet-url username" href="/user/ds" data-screen-name="ds" rel="nofollow">ds</a>"
Passing the above string in .Msg (using golang template) :
<div class="panel-body" >
<p > {{.Msg}} </p>
</div>
Expected outcome is: Hello #ds (with clickable link on #ds)
However getting everything in text format (same as input).
#<a class="tweet-url username" href="/user/ds" data-screen-name="ds" rel="nofollow">ds</a>
What am I missing?
Got a better solution. First of all I am doing htmlEscape on the input then store it in db, then while presenting adding links followed by using document.write(string) function. With this I dont have to change the template and I dont have to worry about XSS attach. Also I am also avoiding XSS scripts in my database. –
Try wrapping your string (Msg) in template.HTML to disable the escaping that html/template does.
Example from the docs:
The template
Hello, {{.}}!
can be invoked with
tmpl.Execute(out, template.HTML(`<b>World</b>`))
to produce
Hello, <b>World</b>!
instead of the
Hello, <b>World<b>!
that would have been produced if {{.}}
was a regular string.
Note that you should do this with great care... make sure that you trust the string you're wrapping in template.HTML. This is an easy way to open yourself up to XSS attacks.

Simple code to read local file from a selection from dropdown box and display it in a textarea (Javascript/ XHTML)

I've been trying for days to create a simple code to create a page that can display text files from a local directory. These are the specifications.
XHTML/ Javascript only
Files are local and from the same directory as the homepage
Files are in txt/ log form
Files to be displayed are to be selected from a dropdown box
Files are to be displayed in a text area
Compatible for all web browsers, can't use ActiveXObject
This was my closest attempt.
JavaScript
function populate(filename)
{
var file = document.getElementById('log1').files.(0);
var reader = new FileReader();
reader.onload = function(e)
{
document.getElementById('myTextarea').value = e.target.result;
};
reader.readAsText(file);
}
(X)HTML
<div id="source1">
<form id="log1">
Select File from cng1wlsbe1b:<br />
<select name="file1">
<option value="CCS1be1" onclick="populate('log1','ACCS1be1.txt')">CCS1be1</option>
<option value="CCS1beadm1" onclick="populate('log1','cng1wlsbe1bCCS1beadm1.txt')">CCS1beadm1</option>
<option value="engine_A" onclick="populate('log1','cng1wlsbe1bengine_A.txt')">engine_A</option>
</select>
</form>
<textarea rows="10" id="myTextarea" name="comment" form="log1" style="width:100%"></textarea>
</div>
I just learned coding and I've been taking in bits and pieces of codes from everywhere, so I'm quite sure it's littered with errors. Will any kind Samaritan please enlighten me?
Thank you!
Robin :)
I have enough time to at least get you on track with some very insightful things that will put gas in your tank and across the desert.
Use XHTML5 (file names ending with .xhtml until you learn how to work with server code). HTML is parsed (looked at and done stuff with) by the HTML parser which is akin to the army recruiting 4channers only there will be no lulz. XHTML is rendered by the XML parser, it's strict and while not perfect it will (while using Firefox) tell you when you reload the page what the error is as well as what line and column it's located at so you can fix the problem now instead of lulz-wat-problem?
In JavaScript when you have an array (more than one item being contained it will use solid brackets. In example document.getElementById('example)is singular though if you want to usedocument.getElementsByTagName('a)[0] it will use [0] for the first occurrence, [1] for second, [2] for third and so forth (without quotes).
Use double quotes for (X)HTML <element attribute="values" /> and single quotes for JavaScript syntax, it will save you a lot of hassle in the future. Also don't mind the whitespace, if you code well you'll use minimal spaces and only ever have more than one space in a row (or more) in JavaScript and your server (aka back-end) code. HTML is text/html whereas XHTML is only XHTML if it's served as application/xhtml+xml; what version the (X)HTML is has nothing to do with the media type/mime.
When in doubt check MDN (Mozilla Developer Network). Just append mdn to your search queries. https://developer.mozilla.org/en/docs/Web/API/FileReader
Never use a framework if you want to be competent, most people can't do actual real code and the more dependencies you add the weaker your code becomes and the easier an update to something third party will break everything...on your wedding day.
Use WinMerge to compare old code to new code, it's freeware and I've never stopped using it.
Use your browser's developer tools (specifically the console) when trying to debug any JavaScript code. Keep in mind that not all errors will produce output, silent errors suck and hopefully you won't have to deal with silent errors for a good while.
Save this code using Notepad++ and ensure it's encode as UTF-8 without a BOM (byte order mark) which is only necessary for UTF-16 (you won't be using that unless you're exceptionally local to India I think it is). There is no perfect editor though for freeware once you get used to it you'll find it fairly capable and not sucking up 4GB of RAM, a very respectable balance.
I've cleaned up the code in general and made a basic application. I've never worked with local text files...I know that the user will have to initiate a request to the client (while testing your computer is both the client and the server). The user will have to use a file input element to select files before anything can happen.
This is a fairly advanced topic for you to take on initially though with enough tenacity you'll be able to conquer it.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Sample XHTML5 Application</title>
<script defer="defer" type="application/javascript">
//<![CDATA[
function populate(filename)
{
var file = document.getElementById('log1').files[0];
var reader = new FileReader();
reader.onload = function(e)
{
document.getElementById('myTextarea').value = e.target.result;
};
reader.readAsText(file);
}
//]]>
</script>
<style type="text/css">
</style>
</head>
<body>
<form id="log1">
<fieldset>
<p>Select File from cng1wlsbe1b:</p>
<input onclick="populate(document.getElementById('file1').value);" type="button" value="clicky clicky" />
<input id="file_upload" type="file" value="" />
<select id="file1" name="file1">
<option value="CCS1be1" onclick="populate('log1','ACCS1be1.txt')">CCS1be1</option>
<option value="CCS1beadm1" onclick="populate('log1','cng1wlsbe1bCCS1beadm1.txt')">CCS1beadm1</option>
<option value="engine_A" onclick="populate('log1','cng1wlsbe1bengine_A.txt')">engine_A</option>
</select>
<textarea rows="10" id="myTextarea" name="comment" form="log1" style="width:100%"></textarea>
</fieldset>
</form>
</body>
</html>
This won't directly answer your question though it will help you get a couple years past the challenges you'd face on your own and put you in striking distance of your goal. Good luck!

How to serialize text that contains mixed HTML & XML to a string?

This might be ridiculous, but I have a C# function that returns a string to JavaScript via AJAX. The first part of the string is HTML, and the second part is XML. The string will look something like:
"""
<b>Some HTML</b> - this entire string is returned from the server.
<i>I have no control over it</i>.
<br/>
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
</catalog>
</xml>
"""
Then I have a function that creates a jQuery UI modal dialogue that contains this string as the main text. It correctly renders the first part as HTML, but the second part (the XML) is invisible
What I need is to render the HTML as it is now, but also render out the XML as a plaintext string (as you see in the example above). Ideally, I would like a server-side solution, but I am guessing it has to be client-side.
I would use something like new XMLSerializer()).serializeToString(combinedString) but won't that also get rid of the HTML tags?
Note: I do not know the HTML text ahead of time. I don't know if it will be seperated by newlines, <p> tags, <div>'s, or whatever else, so I can't exactly do something like String.Split('\n').
You should HTML encode the XML portion in the server side before returning the result to the client. Use HttpUtility.HtmlEncode function to complete this task.
For further details:
https://msdn.microsoft.com/en-us/library/system.web.httputility.htmlencode(v=vs.110).aspx

Use multiple transfer numbers in JavaScript and vxml

I have an interesting task that I am trying to accomplish. While using VoiceXML, I'd like to have a caller call into a number, and then be transferred to number #1. If the caller is not connected (no answer) then the destination number is changed and the caller is then attempted to be connected to the second number.
I was given a little information by the support tech that stated:
The best option would be define a list of numbers in JavaScript, if the transfer is unsuccessful, pop the next of the list, and repeat the transfer (which means the 'dest' for the transfer would be a variable).
But I am not sure how to go about this, and so far, I'm unable to find any reference points to use for this. Could this be achieved by using PHP, maybe?
How can I add JavaScript to VoiceXML that would allow me to set a timeout variable on the transfer tag, and then cycle through the numbers if the caller isn't connected?
Assuming that you use a VoiceXML 2.1 compliant platform, you must use something like <transfer type="consultation" destexpr="myDestinationVariable" connecttimeout="20s" />.
However, the connecttimeout attribute cannot be a JavaScript expression, it must be a time literal. So you need to generate VoiceXML on the fly (with PHP or something else) if the time-out is not a constant.
If you can have a constant timeout, you could do something like (not tested):
<?xml version="1.0" encoding="utf-8"?>
<vxml version="2.1" xml:lang="en-US" xmlns="http://www.w3.org/2001/vxml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<var name="destinations" expr="['5555551111', '5555551112', '5555551113']" />
<var name="currentDestination" expr="destinations.shift()" />
<form id="myForm">
<transfer name="transferResult" type="consultation" cond="currentDestination!=undefined" destexpr="currentDestination"
connecttimeout="20s">
<filled>
<if cond="transferResult=='noanswer'">
<assign name="currentDestination" expr="destinations.shift()" />
<clear />
</if>
</filled>
<catch event="connection.disconnect.transfer">
<!-- transfer OK -->
</catch>
</transfer>
<block>
<!-- No more numbers to try -->
</block>
</form>
</vxml>

Categories

Resources