I have a javascript function(.sjs) which will return a string.
Now, I've to write a xquery transformation which will be triggered through dmsdk. Xquery function will accept a json doc, inside this transformation i need to trigger that javascript function which will return a string. Now, I need to use that string as a uri to load documents..
I've no idea on xquery!!
myXquery transformation function(jsonDoc)
{
/////////////////
myJavaScript function- which return a string
load the doc using this string as uri
}
Use Below query:
declare namespace local ="local";
declare function local:transformation($json-input, $json-uri as xs:string)
{
xdmp:save(concat("D:\", $json-uri), $json-input)(:Here I saved file on local path, If you want to save on Marklogic-DB use-: xdmp:document-insert( $json-uri, $json-input) :)
};
(:1:)
let $input := '{"menu":{"id":"file", "value":"File"}}'
for $json-input in $input
(:2 Call here your Javascript function for json-uri :)
let $json-uri :="json_first.json"
return local:transformation(xdmp:unquote($json-input), $json-uri)
Related
I have an XQuery function to convert a group of XML files to HTML and Zip them. It runs a trasform on each file to create <entry> elements.
Starting with that function:
declare function xport:make-sources( $path as xs:string) as item()* {
for $article in collection(xmldb:encode-uri($path))
let $docnum := $article/article/div[#class = 'content']/#doc/string()
return
<entry name="{concat($docnum,'.html')}" type='text' method='store'>
{transform:transform($article, doc("/db/EIDO/data/edit/xsl/doc-html.xsl"), <parameters/>)}
</entry>
} ;
Given the input, I run the XQuery to just show me the result of the transformation ... and I see this (exactly what I would expect):
<entry name="LS01.html" type="text" method="store">
<html>
<head>
<style>
body {
font-family: Arial;
}
article img {
width:50%;
}
...
You will note the this entry and all of them have no XML Declaration at all.
But now let's put it all together and send those entries to compression. This is all inside a web application. The full XQuery is this:
xquery version "3.0";
import module namespace transform = "http://exist-db.org/xquery/transform";
declare namespace xport = "http://www.xportability.com";
declare function xport:make-sources( $path as xs:string) as item()* {
for $article in collection(xmldb:encode-uri($path))
let $docnum := $article/article/div[#class = 'content']/#doc/string()
return
<entry name="{concat($docnum,'.html')}" type='text' method='store'>
{transform:transform($article, doc("/db/EIDO/data/edit/xsl/doc-html.xsl"), <parameters/>)}
</entry>
} ;
let $path := request:get-parameter("path", "")
let $filename := request:get-parameter("filename", "")
let $col := xport:make-sources($path)
return
response:stream-binary(
xs:base64Binary(compression:zip($col,true()) ),
'application/zip',
$filename
)
Everything works, I get a ZIP file of all the documents that have been transformed to HTML from the XML.
BUT, when I look at the actually file in the ZIP, it has this:
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
The XML Declaration is not on any of the entries to ZIP. It does not exist anywhere (as it couldn't) in the list of entries. But the action of zipping them apparently is adding the declaration. I see no other reason or way. Even specifying omit-xml-declaration or changing the output type in the XSL to text or HTML makes no difference. And this is of course, because the entry list to zip is shown above and that shows the declaration is not there after the transformation.
The files in the ZIP have an added XML declaration, period.
Is there some workaround?
The XML declaration is introduced implicitly in your query when the contents of your zip-bound <entry> elements are passed to the compression:zip() function. I'd advise setting serialization options explicitly using the fn:serialize() function. Here is sample code showing how to achieve the result you describe:
xquery version "3.1";
let $node := <html><head/><body><div><h1>Hello World!</h1></div></body></html>
let $serialized := serialize($node, map { "method": "xml", "indent": true(),
"omit-xml-declaration": true() })
let $entries := <entry name="test.html" type="text" method="store">{$serialized}</entry>
let $filename := "test.zip"
return
response:stream-binary(
compression:zip($entries, true()),
'application/zip',
$filename
)
Saving this query into the database at a location like /db/apps/my-app/test.xq and calling it by pointing your web browser at http://localhost:8080/exist/apps/my-app/test.xq will cause your browser to download test.zip. Opening this zip file will reveal a test.html file absent the XML declaration:
<html>
<head/>
<body>
<div>
<h1>Hello World!</h1>
</div>
</body>
</html>
Stepping back to the fundamentals, the presence or absence of the XML declaration in XQuery is toggled via the omit-xml-declaration serialization parameter. To omit the XML declaration globally for an entire query, you can place this set of declarations in the prolog of your query:
declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "xml";
declare option output:omit-xml-declaration "yes";
Or, when serializing locally within a portion of a query, you can pass this same set of parameters to the fn:serialize function as a map (the method used in the code sample above):
fn:serialize($node, map { "method": "xml", "omit-xml-declaration": true() } )
(There is also an XML syntax for the 2nd options parameter.)
The current version of eXist (v4.0.0) and recent versions (probably since v3.6.0 or so) support all of the options above, and all versions support a somewhat more compact eXist-specific serialization facility, using the exist:serialize option expressed as a string consisting of key=value pairs:
declare option exist:serialize "method=xml omit-xml-declaration=yes";
You can set eXist's default serialization behavior in your conf.xml configuration file. The defaults in conf.xml can be overridden with the methods above. Serialization behavior over different interfaces in eXist, such as WebDAV or XML-RPC, typically respect the defaults set in conf.xml, but these defaults can be overridden on a per-interface basis; for example, see the documentation on serialization over eXist's WebDAV interface.
I'm trying to do some refactoring on a project. I want to replace the code between the lines and with the two commented lines above it so I can use it on another page where I need the quote object
//quote.LoadActive();
//QuoteID = quote.Id;
//--------------------------------------------------------
List<Quote> DBquotes = session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.ToList();
foreach (Quote q in DBquotes)
{
if (q.IsActive)
{
QuoteID = q.Id;
quote = session.Load<Quote>(q.Id);
}
}
//--------------------------------------------------------
Here's the LoadActive() function inside the Quote class
public Quote LoadActive()
{
List<Quote> DBquotes = session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.ToList();
foreach (Quote q in DBquotes)
if (q.IsActive)
return session.Load<Quote>(q.Id);
return new Quote();
}
But I don't know how to actually update the quote object. I can't update inside the function without doing it element by element and that's too tedious. If I try and do quote = quote.LoadActive() then it complains that quote hasn't been initialized. I'm sure there's a way to set up what I'm trying to do but I'm blanking and can't think of good keywords to google my question. I couldn't even come up with a good subject wording for this post!
EDIT: tl;dr I need to load the active quote into the 'quote' object to be used by the page. What's in between the lines works, I want to replace all with the commented lines above (or something similar).
You're Quote object should not be responsible for accessing the database. You should be using some Data Access class or even better yet, a Query Handler to access the DB.
I think you might be a little confused as to what the code is doing. Let me try to explain.
public Quote LoadActive()
{
//This call returns every Quote Document in the DB
//RavenDB by default will only return a Max of 128 w/out doing paging
List<Quote> DBquotes = session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.ToList();
//This doesn't make any sense. You're saying the first quote that is active,
//make another expensive DB call and return the same object.
//I still don't know what you want to do, but you already have the quote object
//why would you go to the DB and get something that you already have?
foreach (Quote q in DBquotes)
if (q.IsActive)
return session.Load<Quote>(q.Id);//Unnecessary, you have the Quote already
//return q;
return new Quote(); //if there's no active quotes just return an Empty Quote Object
}
Are you trying to return all Active Quotes from the DB?
You can do this
var activeQuotes = session.Query<Quote>()
.Where(x => x.IsActive == true)
.ToList();//Remember, RavenDB's safe by default feature
//will only return 128 records, you have to
//implement paging
If you are trying to just return the first IsActive quote (which is what it looks like you want to do from your code) you can simply do:
public Quote LoadActive()
{
return session.Query<Quote>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(x => x.IsActive);
}
Edit based on comment:
This will allow you to accomplish what you want by
QuoteId = quote.LoadActive().Id;
ASPxClientSpinEdit.prototype.NewMethod = function () { alert("MyMethod"); }
var a = ASPxClientSpinEdit.Cast(s);
a.NewMethod();
How if I don't want to use ASPxClientSpinEdit.Cast();
My motto is to call a Java script function at the end of button click code behind. ie, firstly i need to execute the server side function after which my java script function should get invoked.
My server side method is as follows
protected string SaveEmbedURL_click()
{
if (txtembedurl.Text != null)
{
School aschool = new School();
aschool.SchoolId = CurrentSchool.SchoolId;
aschool.EmbedUrl = txtembedurl.Text;
SchoolRespository.updateEmbedUrl(aschool);
return "true";
}
}
My Java script function is as follows
function SaveEmbedUrlClientSide() {
admin_CustomizeTheme.SaveEmbedURL_click(true);
$('#lbl_embedcode').removeClass('hide').addClass('show');
$('#embedCode').removeClass('hide').addClass('show');
CopyToClipboard("embedCode");
}
How can i achieve this?
Thanks.
I'm pretty sure all you need is to add this
RegisterStartupScript("YourJavaScript", "SaveEmbedUrlClientSide()");
"YourJavaScript" is an arbitrary string that is used to identify the Javascript.
Here's the relevant MSDN article.
Page.RegisterStartupScript is now obsolete, so I would use this code.
ClientScript.RegisterStartupScript(Page.GetType, "Javascript", "SaveEmbedUrlClientSide();", true);
RegisterStartupScript requires Type, Reference, Code, render script blocks. Reference Here
I am using the JSON2 script in an asp page to parse JSON post data.
After parsing the data, I have an object in VBScript that allows for notations such as:
jsonData.key
I wish to parse through all the keys, however, I have no knowledge of the key names.
How would I go about doing this?
Example JSON:
{ "dbtable":"TABLE1", "dbcommand": "INSERT", "dbfilter": "ID" }
Thanks
You need to enumerate the property names of the object however this is a very alien thing to do in VBScript. You will need to build some other Jscript functions to assist converting the object into something more easily consumed in VBScript.
If the data is really as simplistic as the example in the question then you could use this function:-
function toDictionary(o)
{
var result = Server.CreateObject("Scripting.Dictionary");
for (var key in o)
result.Add(key, o[key]);
return result;
}
Now in VBScript:-
Dim myData: Set myData = toDictionary(jsonData);
For Each Key In myData
'' // Each Key is a property for jsonData
Next