I am currently working on an application that takes two xml files and compares them with XSLT 2.0 called from Javascript.
I am passing in parameters to the XSLT from my javascript like so:
xsltProcessor.setParameter(null, "testParameter", "I AM A TEST PARAMETER HEAR ME ROAR");
xsltProcessor.setParameter(null, "InputDirectory", "file:///D:/WORKSPACE/results_comparison_1.1/testng-results.xml");
And I am able to display these in the XSLT like so:
<xsl:value-of select="$testParameter" />
<xsl:value-of select="$InputDirectory"/>
Which gives me this output when I load the file up in my browser:
I AM A TEST PARAMETER HEAR ME ROARfile:///D:/WORKSPACE/results_comparison_1.1/testng-results.xml
All fine so far.
My problem:
The trouble is that I have a hardcoded variable like this, which I want to be assigned by an external parameter:
<xsl:variable name="reportFile" select="document('file:///D:/WORKSPACE/results_comparison_1.1/testng-results.xml')" />
I have tried something like:
<xsl:variable name="reportFile" select="document('$InputDirectory')" />
When InputDirectory corresponds to the parameter above. But it does not seem to work. Furthermore when I try to print it using something like this:
<xsl:value-of select="$reportFile" />
I get no error at all when I would usually get a long complicated error message showing up on the screen, which would seem to imply to me the "types" are different.
I was wondering how exactly I can get an xml file from external parameters in this way? Thanks very much.
It sure looks like the issue is here:
<xsl:variable name="reportFile" select="document('$InputDirectory')" />
This is telling it to load a document called "$InputDirectory". Instead, do this:
<xsl:variable name="reportFile" select="document($InputDirectory)" />
Related
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.
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!
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
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>
I have a value coming from SharePoint as <xsl:value-of select="#fldNm" />
This will have 1 of 2 possible values: an empty string, or 'yes.' This is within <xsl:template name="dvt_1.rowedit"> of a SharePoint display form.
If the value is an empty string, I want to dislpay one character, but if it is 'yes' I want to display a different character.
I am putting a tag inline with the HTML, and using document.write(). But I am having no luck making the actions respond to the value of fldNm.
I have found a lot of examples, but they are so different than what I am trying to do that I can't make sense of them.
This is the situation:
When you create a SharePoint Custom List, 3 .aspx pages are created for you: newForm, editForm and dispForm.
These .aspx pages are loaded with all kinds of xsl and xslt functionality. Several xsl templates are created, one of which holds the HTML that will show when the .aspx is used. That template is named by SharePoint as 'dvt_1.' That template is then called in a <xsl:for-each select="$Rows"> xsl structure.
Within that called template on the dispForm page, each datum is shown through the use of
<td>
<div>
<xsl:value-of select="#fieldName" />
</div>
</td>
When the page is rendered, that 'value-of' tag is replaced with the contents of whatever field was psecified (of course).
In my case, because of the Design Requirements document, the field I am asking about will contain 'yes' or ''.
If it is yes, I want to use a put a single character there indicating the 'yes.' Otherwise I want to put a different character there, indicating 'not yes.'
I cannot figure out how to get the rendered value into a choice-making construct.
I tried something like
<td>
The answer is: <script> if (<xsl:value-of select="#fieldName" /> == 'yes') {
document.write('A');
} else {
document.write('B');
}
</script>
</td>
but the xsl tag was not recognized as such.
I am very new to xsl, and though I am starting to see how the syntax accomplishes things, it is still very mysterious to me.
Since you haven't provided us much info, this is the best answer I can give.
As shown in this answer:
A more general XPath 1.0 expression that produces the string $s1 if
$val is "x" and produces the string $s2 if $val is "y" :
concat(substring($s1, 1 div ($val = "x")),
substring($s2, 1 div ($val = "y"))
)
If I understand your question correctly, this principle can be used to generate the expected answer. To see this, look at the following sample:
Assumptions:
A value of "yes" should output the character "a"
A value of "" should output the character "b"
When this XSLT (which uses the aforementioned XPath):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="e">
<xsl:text>The value is: </xsl:text>
<xsl:value-of
select="concat(substring('a', 1 div (#fldNm = 'yes')),
substring('b', 1 div (#fldNm = ''))
)"/>
<xsl:text/>
</xsl:template>
</xsl:stylesheet>
...is applied to the following sample XML:
<t>
<e fldNm="yes"/>
<e fldNm=""/>
</t>
...the wanted result is produced:
The value is: a
The value is: b
Use:
substring('yx', 1 + (#fldNm = 'yes'), 1)
The evaluation of this expression produces the character "x" if the value of the attribute (of the context node) named "fldNm" is "yes", otherwise the evaluation produces the character "y".
Here we use the fact that by definition:
number(true()) = 1
and
number(false()) = 0