Pass parameter from a URL to a XSL stylesheet - url

I just spent the past couple of days digging into the messages looking for a way to pass a parameter from an URL to a XSL stylesheet.
for example, I have a current url like:
http://localhost/blocableau/data/base_bloc/blocableau3x.xml?95.2
and I want to just select the value after the ? like the 95.2 in this example, and put it in the variable var_massif.
I tried the following code with javascript for test the value substring(1) but with xsl it didn't work.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<!-- recherche des cotations par Massif selon une variable -->
<xsl:key name="byMassif" match="bloc" use="Massif" />
<xsl:template match="BLOCS">
<script>var requete = location.search.substring(1);
mavariable=requete;alert(mavariable);x=mavariable</script>
<xsl:variable name="var_massif"><xsl:value-of select="95.2" /></xsl:variable>
<span>Ma variable xsl est : <xsl:value-of select="$var_massif"/></span>
<div style="position:relative; top:0px;left:10px;font-family: Arial, 'Helvetica Neue', 'Helvetica, sans-serif'; font-size:12px;z-index:1;">
<!-- genere un id pour chaque valeur de cotation et mise en forme -->
<xsl:for-each select="bloc[generate-id() = generate-id(key('byMassif', $var_massif)[1])]" >
<xsl:sort select="Massif" />

I assume you are loading a XML which uses a XSL processing instruction to transform the file:
<?xml-stylesheet ... ?>
You would need to read the URL and extract the query string. Unfortunately it is not automatically mapped. The only way to do that would be using document-uri(/) but it's XSLT 2.0 and not supported in browsers.
In XSLT 1.0 you would have to direct your HTTP request not to the XML file you want to process, but to a script which will load your XML and XSLT using the XSLTProcessor. Then you could pass the query-string as a parameter to the processor:
var var_massif = location.search.substring(1); // gets the string and removes the `?`
var processor = new XSLTProcessor(); // starts the XSL processor
processor.setParameter(null, "var_massif", var_massif); // sets parameter
... // load XSL, XML and transformToDocument
Inside your XSLT stylesheet you should have a global parameter variable:
<xsl:param name="var_massif" />
Which you will then be able to read with $var_massif.
UPDATE Here is a step-by-step example using JQuery:
I'm using this reduced stylesheet, just to show you how to get the parameter. It's in a file I called stylesheet.xsl:
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<xsl:param name="var_massif" />
<xsl:template match="BLOCS">
<span>Ma variable xsl est : <xsl:value-of select="$var_massif" /></span>
</xsl:template>
</xsl:stylesheet>
And this input (blocableau3x.xml) in the same directory:
<BLOCS>
<bloc>
<Massif></Massif>
</bloc>
</BLOCS>
Now create this HTML file (blocableau3x.html) also in the same directory:
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.js"></script>
<script>
$( document ).ready(function() {
var var_massif = location.search.substring(1); // gets the string and removes the `?`
var body = $("body")[0]; // gets the body element where the result will be inserted
if (var_massif) {
var processor = new XSLTProcessor(); // starts the XSL processor
processor.setParameter(null, "var_massif", var_massif);
var source;
var xslReq = $.get("stylesheet.xsl", function (data) { // loads the stylesheet
processor.importStylesheet(data);
});
var xmlReq = $.get("blocableau3x.xml", function (data) { // loads the xml
source = data;
});
$.when(xslReq, xmlReq).done(function () { // waits both to load
var result = processor.transformToDocument(source); // transforms document
body.appendChild(result.documentElement); // adds result as child of body element
});
} else {
body.html("<h1>Missing query string</h1>"); // in case there is no query string
}
});
</script>
<html>
<body></body>
</html>
Instead of calling your XML file in the URL, call the HTML file. When it loads, it will load the XSL file and the XML file, and use the XSL processor to process the file. It will be able to read the query parameter and pass it as a XSL global parameter, which you can read in your XSLT file.

Related

Show local XML document with WKWebView

I'm trying to display a XML file with WKWebView. Has anyone got it managed to display it? I've set up a complete sample app (see below). The results were obtained by testing on iOS 9.3 iPhone 4S simulator.
LoadFileUrl()
string targetFilepath = Init("simplexsl.xml");
Init("simple.xsl");
NSUrl url = new NSUrl("file:///" + targetFilepath, false);
NSUrl readAccessUrl = new NSUrl("file:///" + Path.GetDirectoryName(targetFilepath), true);
webview.LoadFileUrl(url, readAccessUrl);
Result: white page
LoadHtmlString()
string targetFilepath = Init("simplexsl.xml");
Init("simple.xsl");
NSData documentData = NSData.FromFile(targetFilepath);
if(documentData != null && documentData.Length > 0)
{
NSString htmlString = NSString.FromData(documentData, NSStringEncoding.UTF8);
webview.LoadHtmlString(htmlString, readAccessUrl);
}
Result: content of xml is shown (without tags from xml), but styling is not applied.
NSUrl readAccessUrl = new NSUrl("file:///" + Path.GetDirectoryName(targetFilepath), true);
NSString htmlString = new NSString(File.ReadAllText(targetFilepath));
webview.LoadHtmlString(htmlString, readAccessUrl);
Result: content of xml is shown (without tags from xml), but styling is not applied.
LoadData()
string targetFilepath = Init("simplexsl.xml");
Init("simple.xsl");
NSUrl readAccessUrl = new NSUrl("file:///" + Path.GetDirectoryName(targetFilepath), true);
NSData documentData = NSData.FromFile(targetFilepath);
if(documentData != null && documentData.Length > 0)
{
webview.LoadData(documentData, "text/xml", "utf-8", readAccessUrl);
}
Result: white page
LoadRequest()
string targetFilepath = Init("simplexsl.xml");
Init("simple.xsl");
NSUrl url = new NSUrl("file:///" + targetFilepath, false);
webview.LoadRequest(new NSUrlRequest(url));
Result: white page
Different paths
var documents = NSFileManager.DefaultManager.GetUrls(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomain.User) [0].Path;
var caches = Path.Combine (documents, "Caches");
Result: white page
var caches = Path.Combine(System.IO.Path.GetTempPath(), "www");
Directory.CreateDirectory(caches);
Result: white page
Bundle Resource
string folder = NSBundle.MainBundle.BundlePath;
string source = Path.Combine(folder, "simplexsl.xml");
webview.LoadFileUrl(new NSUrl(source,false), new NSUrl(folder, true))
Result: white page
Link
Now I loaded a html with a link in it
XML Link
Result: html page is loaded, clicking the link leads to a white page, if xsl is commented out in xml then the xml is shown without styling
Online
webview.LoadRequest(new NSUrlRequest(new NSUrl("http://www.w3schools.com/xml/simplexsl.xml")));
Result: WKWebView can show the XML file if you allow it load non https resources.
Without XSL
Comment out the following line in simplexsl.xml
<?xml-stylesheet type="text/xsl" href="simple.xsl" ?>
and using
webview.LoadFileUrl(url, readAccessUrl);
Result: content of xml is shown (without tags from xml), but styling is not applied. So it seems that there is a basepath issue, but only with XSL files?
Displaying a html file, which references a picture relatively, does work, when I use LoadFileUrl(). But with xml files there seems to be a problem. For a short test UIWebView seems to handle that better.
So how is it done correctly?
Basic setup
public override void ViewDidLoad()
{
base.ViewDidLoad();
var webview = new WKWebView(View.Bounds, new WKWebViewConfiguration());
View.AddSubview(webview);
// code here
}
private string Init(string filename)
{
string sourceFilepath = Path.Combine(NSBundle.MainBundle.BundlePath, filename);
var library = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments).Replace("Documents", "Library");
var caches = Path.Combine(library, "Caches");
var targetFilepath = Path.Combine(caches, filename);
if (CopyFile(sourceFilepath, targetFilepath))
return targetFilepath;
return string.Empty;
}
private bool CopyFile(string sourceFilepath, string targetFilepath)
{
if (File.Exists(sourceFilepath))
{
File.Copy(sourceFilepath, targetFilepath, true);
return true;
}
return false;
}
targetFilepath is something like /Users/some-user/Library/Developer/CoreSimulator/Devices/8808B80D-D232-4599-B776-139409C9DDB8/data/Containers/Data/Application/BC84CFD0-A805-417C-912F-C2B07834C822/Library/Caches/simplexsl.xml
simplexsl.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="simple.xsl" ?>
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>two of our famous Belgian Waffles with plenty of real maple syrup</description>
<calories>650</calories>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<description>light Belgian waffles covered with strawberries and whipped cream</description>
<calories>900</calories>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<description>light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
<calories>900</calories>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<description>thick slices made from our homemade sourdough bread</description>
<calories>600</calories>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<description>two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
<calories>950</calories>
</food>
</breakfast_menu>
simple.xsl
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
<xsl:for-each select="breakfast_menu/food">
<div style="background-color:teal;color:white;padding:4px">
<span style="font-weight:bold">
<xsl:value-of select="name"/> -
</span>
<xsl:value-of select="price"/>
</div>
<div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
<p>
<xsl:value-of select="description"/>
<span style="font-style:italic">
(<xsl:value-of select="calories"/> calories per serving)
</span>
</p>
</div>
</xsl:for-each>
</body>
</html>
It would be no problem if you post your solutions in Objective-C or Swift.
I've the bad feeling, that the XSL transform is not allowed for local files (despite in the same directory) because of security concerns. If I open the file in Chrome I get
Unsafe attempt to load URL file:///C:/some/path/Projects/TestWKWebView/TestWKWebView/Resources/simple.xsl from frame with URL file:///C:/some/path/Projects/TestWKWebView/TestWKWebView/Resources/simplexsl.xml. 'file:' URLs are treated as unique security origins.
Firefox works fine. In Edge I get
XSLT8690: The system cannot locate the object specified.
Very interesting comment from here:
Interesting fact: Safari on Mac (8.0) works just fine with local XSLT, but Safari on iOS (8) simulator (and I suppose on iOS as well) I got the same error like in Chrome "Domains, protocols and ports must match.". But if I'm to implement UIWebView in the app and load XML with XSLT everything works OK.
After some research it seems that there are the following solutions:
Use UIWebView
Use a local webserver (e.g. look here)
Perhaps do the XSLT yourself with the help of libxslt (see here or here, also available as NuGet package)

how to extract the value of specefic div in html with crawling in apache nutch?

I do crawling with nutch 2.2 and the data that i retrieve is the metatag,how to extract the value of specefic div in html with crawling in apache nutch
You will have to write a plugin that will extend HtmlParseFilter to achieve your goal.
You can use some html parser like Jsoup for this and extract URLs that you want and add them as outlinks.
Sample HtmlParseFilter implementation:-
public ParseResult filter(Content content, ParseResult parseResult,
HTMLMetaTags metaTags, DocumentFragment doc) {
// get html content
String htmlContent = new String(content.getContent(), StandardCharsets.UTF_8);
// parse html using jsoup or any other library.
Document document = Jsoup.parse(content.toString(),content.getUrl());
Elements elements = document.select(<your_css_selector_query);
// modify/select only required outlinks
if (elements != null) {
Outlink outlink;
List<String> newLinks=new ArrayList<String>();
List<Outlink> outLinks=new ArrayList<Outlink>();
String absoluteUrl;
Outlink outLink;
for (Element element : elements){
absoluteUrl=element.absUrl("href");
if(includeLinks(absoluteUrl,value)) {
if(!newLinks.contains(absoluteUrl)){
newLinks.add(absoluteUrl);
outLink=new Outlink(absoluteUrl,element.text());
outLinks.add(outLink);
}
}
}
Parse parse = parseResult.get(content.getUrl());
ParseStatus status = parse.getData().getStatus();
Title title = document.title();
Outlink[] newOutLinks = (Outlink[])outLinks.toArray(new Outlink[outLinks.size()]);
ParseData parseData = new ParseData(status, title, newOutLinks, parse.getData().getContentMeta(), parse.getData().getParseMeta());
parseResult.put(content.getUrl(), new ParseText(elements.text()), parseData);
}
//return parseResult with modified outlinks
return parseResult;
}
Build new plugin using ant and add plugin in nutch-site.xml.
<property>
<name>plugin.includes</name>
<value>protocol-httpclient|<custom_plugin>|urlfilter-regex|parse-(tika|html|js|css)|index-(basic|anchor)|query-(basic|site|url)|response-(json|xml)|summary-basic|scoring-opic|urlnormalizer-(pass|regex|basic)|indexer-elastic</value>
</property>
And in parser-plugins.xml you can use your custom plugin instead of default plugin used by tika by something like this :-
<!--
<mimeType name="text/html">
<plugin id="parse-html" />
</mimeType>
<mimeType name="application/xhtml+xml">
<plugin id="parse-html" />
</mimeType>
-->
<mimeType name="text/xml">
<plugin id="parse-tika" />
<plugin id="feed" />
</mimeType>
<mimeType name="text/html">
<plugin id="<custom_plugin>" />
</mimeType>
<mimeType name="application/xhtml+xml">
<plugin id="<custom_plugin>" />
</mimeType>
You need to override the parsefilter and use Jsoup selector to select particular div.

Microsoft XmlLite fails to detect end-of-element

I'm using Microsoft's XmlLite DLL to parse a simple XML file, using the code in the example XmlLiteReader. The essential part of the code (C++) is
while(S_OK == (hr = pReader->Read(&nodeType)))
{
switch(nodeType)
{
case XmlNodeType_Element:
// Get name...
WriteAttributes(pReader, es, attributes);
break;
case XmlNodeType_EndElement:
// Process end-of-element...
break;
}
and
HRESULT WriteAttributes(IXmlReader* pReader, CString& es, StringStringMap& attributes)
{
while(TRUE)
{
// Get and store an attribute...
HRESULT hrMove = pReader->MoveToNextAttribute();
}
// ...
}
So, here's my question. With XML input such as
<?xml version="1.0" encoding="utf-8"?>
<settings version="1.2">
<runID name="test" mode="N" take_data="Y">
<cell id="01">
<channel id="A" sample="something"/>
<channel id="B" sample="something else"/>
</cell>
<cell id="03">
<channel id="A" sample="other something"/>
<channel id="B" sample="other something else"/>
</cell>
</runID>
</settings>
Everything works as expected, except that the /> at the end of each channel line, which indicates the end of the element channel, isn't recognized as the end of an element. The successive node types following channel are whitespace (\n), then element (the second channel).
How can I determine from XmlLite that element `channel' has ended? Or am I misunderstanding the XML syntax?
You can test if an element ends with /> by using the function IsElementEmpty.

Get an entry of a Manifest file with ant

I am trying to develope an Ant macrodef which gets the values separated by commas of the Require-Bundle property in a Manifest file passed as parameter. What I want to obtain is something like this:
Require-Bundle=org.eclipse.ui,org.eclipse.ui.ide,org.eclipse.ui.views...
The problem I am facing in my code is that it doesn't take into account if the property has multiple values in multiple lines, here is my code:
<macrodef name="getDependencies">
<attribute name="file" />
<attribute name="prefix" default="ant-mf." />
<sequential>
<loadproperties>
<file file="#{file}" />
<filterchain>
<linecontains>
<contains value="Require-Bundle" />
</linecontains>
<prefixlines prefix="#{prefix}" />
</filterchain>
</loadproperties>
</sequential>
</macrodef>
But this is what I get:
[echoproperties] ant-mf.Require-Bundle=org.eclipse.ui,
Any help will be appreciated.
Most likely, your Manifest file looks like this:
Require-Bundle: org.eclipse.ui,
org.eclipse.ui.ide,
org.eclipse.ui.views,
...
Unfortunately, Java Manifest files aren't quite Java Properties files. Manifest files can have attributes that span multiple lines whereas Property files can't have multi-line values. The <loadproperties> task can't handle multi-line attributes.
Instead, you'll need an Ant task that knows about Manifest files. In another question, Richard Steele provides Ant script that loads a Manifest file from a Jar file. You can adapt the example to get just the Require-Bundle attribute.
Thanks to Chad Nouis I have changed the macrodef approach to scriptdef. I have debugged and adapted the Richard Steele script to fit my needs:
<!--
Loads entries from a manifest file.
#manifest A manifest file to read
#entry The name of the manifest entry to load (optional)
#prefix A prefix to prepend (optional)
-->
<scriptdef name="getDependencies" language="javascript" description="Gets all entries or a specified one of a manifest file">
<attribute name="manifest" />
<attribute name="entry" />
<attribute name="prefix" />
<![CDATA[
var filename = attributes.get("manifest");
var entry = attributes.get("entry");
if (entry == null) {
entry = "";
}
var prefix = attributes.get("prefix");
if (prefix == null) {
prefix = "";
}
var manifest;
if (filename != null) {
manifest = new java.util.jar.Manifest(new java.io.FileInputStream(new java.io.File(filename)));
} else {
self.fail("File is required");
}
if (manifest == null) {
self.log("Problem loading the Manifest");
} else {
var attributes = manifest.getMainAttributes();
if (attributes != null) {
if (entry != "") {
project.setProperty(prefix + entry, attributes.getValue(entry));
} else {
var it = attributes.keySet().iterator();
while (it.hasNext()) {
var key = it.next();
project.setProperty(prefix + key, attributes.getValue(key));
}
}
}
}
]]>
</scriptdef>

PersistenceManager issue

I have written a code to save my screen data and retrieve it for second time. Code is:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="HomeView"
add="addHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.managers.PersistenceManager;
protected function saveButton_clickHandler(event:MouseEvent):void
{
var saveManager:PersistenceManager = new PersistenceManager();
saveManager.setProperty("myText", myInput.text);
}
protected function addHandler(event:FlexEvent):void
{
var loadManager:PersistenceManager = new PersistenceManager();
if(loadManager.load())
{
var savedData:Object = loadManager.getProperty("myText");
if(savedData)
myInput.text = savedData.toString();
}
}
protected function clearButton_clickHandler(event:MouseEvent):void
{
var persistenceManager:PersistenceManager = new PersistenceManager();
persistenceManager.clear();
myInput.text = "";
}
]]>
</fx:Script>
<s:TextInput width="100%" id="myInput"/>
<s:Group width="100%">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
</s:Group>
<s:Button id="saveButton" x="-1" y="65" width="100%" label="Save"
click="saveButton_clickHandler(event)"/>
<s:Button id="clearButton" x="0" y="116" width="100%" label="Clear"
click="clearButton_clickHandler(event)"/>
But, when I packaging it for deploying on iPad, it gives me a error like:
Error occurred while packaging the application:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
Compilation failed while executing : ADT
I am using Flash builder 4.5 to create iOS application.
Thanx in advance
You need to modify your FlashBuilder.ini file
It's located in your FlashBuilder installation directory.
You need to modify the Xms size - this will allocate more memory while compiling and building project. Remember it should be in strongs of 2.
My file looks like this:
launcher.defaultAction
openFile
-nl
en_US
-vmargs
-Xms256m
-Xmx512m
-XX:MaxPermSize=256m
-XX:PermSize=64m

Resources