XML as an value of html input attribute using XSLT - xslt-2.0

I have an XML like below.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myxml SYSTEM "xyz.dtd">
<myxml payloadID="__PAYLOADID__" timestamp="__TIMESTAMP__" xml:lang="en-US">
<Header>
<From>
<Credential domain="test">
<Identity>blahblah&test</Identity>
</Credential>
</From>
</Header>
<Extrinsic name="GroupLineID"/>
</myxml>
I am trying to create HTML page where above XML need to be placed as value of attribute of html Input tag. I am using Java with Saxon to run XSLT. My XSLT is
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/">
<xsl:output name="test" method="xml" encoding="UTF-8" omit-xml-declaration="yes" indent="yes" />
<xsl:template match="/">
<html >
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<xsl:element name="INPUT">
<xsl:attribute name="NAME">xml</xsl:attribute>
<xsl:attribute name="TYPE">HIDDEN</xsl:attribute>
<xsl:attribute name="VALUE"><xsl:copy-of select="saxon:serialize(myxml,'test')"></xsl:copy-of></xsl:attribute>
</xsl:element>
</html>
</xsl:template>
Output of this XSLT is
<html xmlns:saxon="http://saxon.sf.net/">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<INPUT NAME="xml" TYPE="HIDDEN" VALUE="<myxml payloadID="__PAYLOADID__" timestamp="__TIMESTAMP__" xml:lang="en-US">
<Header>
<From>
<Credential domain="test">
<Identity>blahblah&amp;test</Identity>
</Credential>
</From>
</Header>
<Extrinsic name="GroupLineID"/>
</myxml>">
</html>
But i would need to have xml and doctype declaraction also in output like below
<html xmlns:saxon="http://saxon.sf.net/">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<INPUT NAME="xml" TYPE="HIDDEN" VALUE="<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE myxml SYSTEM "xyz.dtd&quote;><myxml payloadID="__PAYLOADID__" timestamp="__TIMESTAMP__" xml:lang="en-US">
<Header>
<From>
<Credential domain="test">
<Identity>blahblah&amp;test</Identity>
</Credential>
</From>
</Header>
<Extrinsic name="GroupLineID"/>
</myxml>">
</html>
Any help appreciated!

Neither the XML declaration nor the DOCTYPE declaration are part of the XSLT data model so the XSLT processor does not have access to those parts of an XML input document. Using http://andrewjwelch.com/lexev/ you might be able to get the DOCTYPE however.

If you want the XML declaration included, why have you said omit-xml-declaration="yes" in the xsl:output declaration?
Similarly, you can get a DOCTYPE declaration in the output of saxon:serialize if you use the doctype-system and doctype-public attributes of xsl:output.

Related

Test for xsi:nil="true"

I wish to test for xsi:nil="true".
I'm using the replies from kjhughes & Michael Kay in these posts, respectively.
How to implement if-else statement in XSLT?
How do I check if XML value is nil in XSLT
XML:
<OSM>
<EstablishmentDetail>
<RatingValue>5</RatingValue>
<RatingDate>2008-05-15</RatingDate>
</EstablishmentDetail>
<EstablishmentDetail>
<RatingValue>AwaitingInspection</RatingValue>
<RatingDate xsi:nil="true"/>
</EstablishmentDetail>
</OSM>
A snip of the XSL:
<xsl:template>
"Value": "<xsl:value-of select="if (nilled(RatingDate)) then RatingValue else 'XX' "/>",
</xsl:template>
It's producing output but both are 'XX'. Is it just a syntax error?
The function https://www.w3.org/TR/xpath-functions/#func-nilled is meant to work with schema-aware XSLT and validated input i.e. if you use Saxon EE you can expect it to do its job:
In practice, the function returns true only for an element node that
has the attribute xsi:nil="true" and that is successfully validated
against a schema that defines the element to be nillable;
Need to add the namespace in the input document:
<OSM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EstablishmentDetail>
<RatingValue>5</RatingValue>
<RatingDate>2008-05-15</RatingDate>
</EstablishmentDetail>
<EstablishmentDetail>
<RatingValue>AwaitingInspection</RatingValue>
<RatingDate xsi:nil="true"/>
</EstablishmentDetail>
</OSM>
I'm not getting the right value out of the standard fn:nilled() function hence substituted a user function:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:l="local:functions">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<RatingValues>
<xsl:for-each select="//EstablishmentDetail">
<EstablishmentDetail index="{position()}" >
<RatingValue>
<xsl:value-of select="('XX'[l:nilled(current()/RatingDate) ],
current()/RatingValue)[1]" />
</RatingValue>
<Nilled>
<xsl:value-of select="nilled(RatingDate)" />
</Nilled>
</EstablishmentDetail>
</xsl:for-each>
</RatingValues>
</xsl:template>
<xsl:function name="l:nilled" as="xs:boolean" >
<xsl:param name="e" as="element()" />
<xsl:sequence select="exists($e/#xsi:nil) and $e/#xsi:nil eq 'true'" />
</xsl:function>
</xsl:stylesheet>
which produces:
<?xml version="1.0" encoding="UTF-8"?>
<RatingValues xmlns:l="local:functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<EstablishmentDetail index="1">
<RatingValue>5</RatingValue>
<Nilled>false</Nilled>
</EstablishmentDetail>
<EstablishmentDetail index="2">
<RatingValue>XX</RatingValue>
<Nilled>false</Nilled>
</EstablishmentDetail>
</RatingValues>
The Nilled elements in the output just to show that I'm getting false for both cases.

Unable to group the element value using group by in XSLT

I have an XML lie below:
<Products>
<Product1>
<Reference>000510143244</Reference>
<Value1>543</Value1>
</Product1>
</Products>
<Products>
<Product1>
<Reference>000510143244</Reference>
<Value1>543</Value1>
</Product1>
</Products>
<Products>
<Product1>
<Reference>45768799322</Reference>
<Value1>543</Value1>
</Product1>
</Products>
<Products>
<Product2>
<Reference>35726318090</Reference>
<Value1>543</Value1>
</Product2>
</Products>
<Products>
<Product2>
<Reference>35726318090</Reference>
<Value1>543</Value1>
</Product2>
</Products>
I want to get only first value of the Product1 reference...but I am unable to get that.Also it is not mandatory that Product 1 will always be the first element in input xml.
Any suggestions how can I get that?
I have tried to get the value as :
<xsl:template match="//Products">
<xsl:variable name="Product1">
<xsl:for-each-group select="/Reference" group-by="/Reference">
<xsl:copy-of select="." />
</xsl:for-each-group>
</xsl:variable>
</xsl:template>
Update:1
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="Products[child::Product1][1]">
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
My expected output is :000510143244
To get the first occurrence of <Products> who has <Product1>, you might need to match the parent tag or root tag of your input XML.
Assuming your input as below:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<root>
<Products>
<Product2>
<Reference>35726318090</Reference>
</Product2>
</Products>
<Products>
<Product1>
<Reference>02563899183</Reference>
</Product1>
</Products>
<Products>
<Product1>
<Reference>000510143244</Reference>
</Product1>
</Products>
<Products>
<Product1>
<Reference>000510143244</Reference>
</Product1>
</Products>
<Products>
<Product2>
<Reference>35726318090</Reference>
</Product2>
</Products>
</root>
The following code can give you the result:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="root">
<xsl:for-each-group select="Products/Product1" group-by="Reference">
<xsl:copy-of select="current-group()[1]" />
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
See the demo: https://xsltfiddle.liberty-development.net/3NJ38Zx
Update:
OR you can simply achieve it by following code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="Products[child::Product1][1]">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
Update 2:
<xsl:template match="root">
<xsl:variable name="ref">
<xsl:for-each-group select="Products/Product1" group-by="Reference">
<xsl:copy-of select="current-group()[1]/Reference" />
</xsl:for-each-group>
</xsl:variable>
<xsl:value-of select="$ref"/>
</xsl:template>
https://xsltfiddle.liberty-development.net/3NJ38Zx/1
Update 3:
You cannot assign a value to global variable from a template.
There are two ways to get what you required.
1) Create a global variable as below which will take first <Products> whose child element is <Product1> and will display it's Reference
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:variable name="ref" select="root/Products[child::Product1][1]/Product1/Reference" />
<xsl:template match="/">
<xsl:value-of select="$ref" />
</xsl:template>
</xsl:stylesheet>
2) You can modify the template as below to get the result.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="Products[child::Product1][1]/Product1/Reference">
<xsl:value-of select="." />
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>

Block entire page

When I change the page (page1 to page2) exists some delay and it is possible to click other buttons and these actions go run. So I would like to block the page during the waiting time for loading the following page, how do I?
I use jsf2 and primefaces.
At this time already tested blockUI and blockUI-extensions -> not work
You should tell us. Why p:blockUI is not work?
Try this. It is work.
page1.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<f:facet name="first">
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta name="viewport"
content="user-scalable=no,
width=device-width,
initial-scale=1.0,
maximum-scale=1.0"/>
</f:facet>
<title>page1</title>
</h:head>
<h:body id="bodyView">
page1
<h:form id="form1">
<p:editor id="editor"
widgetVar="editorWidget"
width="600" />
</h:form>
<h:form id="form2">
<p:blockUI block=":bodyView"
widgetVar="bui"/>
<p:commandButton id="redirect"
value="go to page2"
onclick="PF('bui').show();"
actionListener="#{blockView.redirect}"/>
</h:form>
</h:body>
</html>
page2.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<f:facet name="first">
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8" />
<meta name="viewport"
content="user-scalable=no,
width=device-width,
initial-scale=1.0,
maximum-scale=1.0"/>
</f:facet>
<title>page2</title>
</h:head>
<h:body>
<h:form>
page2
</h:form>
</h:body>
</html>
MangedBean
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
/**
*
* #author Wittakarn
*/
#ViewScoped
#ManagedBean(name = "blockView")
public class BlockView implements Serializable{
public void redirect(ActionEvent event){
try {
Thread.sleep(4000);
FacesContext.getCurrentInstance().getExternalContext().redirect("page2.xhtml");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

How to pass custom facelet tag attr to implementation in JSF 2

I have the next:
/src/main/webapp/WEB-INF/web.xml
<?xml version="1.0" encoding="utf-8"?>
<webapp>
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my-taglib.xml</param-value>
</context-param>
</webapp>
/src/main/webapp/WEB-INF/my-tablib.xml
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://example.com/jsf/taglib</namespace>
<tag>
<tag-name>my-tag</tag-name>
<!-- /src/main/webapp/WEB-INF/tags/com/example/myTag.xml -->
<source>tags/com/example/myTag.xml</source>
</tag>
</facelet-taglib>
/src/main/webapp/WEB-INF/tags/com/example/myTag.xml
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="customAttr" />
</composite:interface>
<composite:implementation>
<h:outputText value="#{cc.attrs.customAttr}" />
</composite:implementation>
</html>
/src/main/webapp/index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:exui="http://example.com/jsf/taglib">
<h:head>
</h:head>
<h:body>
<exui:my-tag customAttr="showMe" />
</h:body>
</html>
As the result, I don't see "showMe" message after war was deployed. How to fix that?
You put the composite component in /resources/<composite name> folder(no need to add my-tablib.xml to web.xml),
for example:
and then you can use by declare:
<html xmlns="http://www.w3.org/1999/xhtml"
...
xmlns:cps="http://java.sun.com/jsf/composite/composites/CPSI35"
>
...
<cps:cpscontact ....></cps:cpscontact>

Getting the XML ID using REXML

I have an XML response as included below. How can I obtain the element?
In rails I have:
xml = REXML::Document.new(contacts_as_xml)
Rails.logger.info xml[1].attributes["id"]
Which is not returning 'user#company.com'
Thanks
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:gContact="http://schemas.google.com/contact/2008" xmlns:batch="http://schemas.google.com/gdata/batch" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/"Ck8BQ38yfyt7I2A9WhNSFk8."">
<id>user#company.com</id>
<updated>2012-10-30T18:14:12.197Z</updated>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
<title>Users's Contacts</title>
<link rel="alternate" type="text/html" href="http://www.google.com/" />
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full" />
<link rel="http://schemas.google.com/g/2005#post" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full" />
<link rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full/batch" />
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full?max-results=10000" />
<author>
<name>User Howdy</name>
<email>user#company.com</email>
</author>
<generator version="1.0" uri="http://www.google.com/m8/feeds">Contacts</generator>
<openSearch:totalResults>2</openSearch:totalResults>
<openSearch:startIndex>1</openSearch:startIndex>
<openSearch:itemsPerPage>10000</openSearch:itemsPerPage>
<entry gd:etag=""QXc5eDVSLit7I2A9WhdSFk8PTgU."">
<id>http://www.google.com/m8/feeds/contacts/myuser%40mysite.com/base/970a99881a51f3</id>
<updated>2011-07-25T20:31:50.920Z</updated>
<app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-25T20:31:50.920Z</app:edited>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
<title>Jon Paris</title>
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/myuser%40mysite.com/970a99881a51f3" />
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full/970a99881a51f3" />
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full/970a99881a51f3" />
<gd:name>
<gd:fullName>Jon Adams</gd:fullName>
<gd:givenName>Jon</gd:givenName>
<gd:familyName>Adams</gd:familyName>
</gd:name>
<gd:email rel="http://schemas.google.com/g/2005#other" address="jon#adams.com" primary="true" />
<gd:email rel="http://schemas.google.com/g/2005#home" address="jon#adams.com" />
</entry>
<entry gd:etag=""R3YzcTFbKit7I2A9WhJbE00ORQY."">
<id>http://www.google.com/m8/feeds/contacts/myuser%40mysite.com/base/1229b5e8eeef3e3</id>
<updated>2012-09-22T08:57:06.889Z</updated>
<app:edited xmlns:app="http://www.w3.org/2007/app">2012-09-22T08:57:06.889Z</app:edited>
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
<title></title>
<link rel="http://schemas.google.com/contacts/2008/rel#photo" type="image/*" href="https://www.google.com/m8/feeds/photos/media/myuser%40mysite.com/1229b5e8eeef3e3" gd:etag=""UQZOJlcjWit7I2BmGBdVTzBfL2E2GGI5Myk."" />
<link rel="self" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full/1229b5e8eeef3e3" />
<link rel="edit" type="application/atom+xml" href="https://www.google.com/m8/feeds/contacts/myuser%40mysite.com/full/1229b5e8eeef3e3" />
<gd:email rel="http://schemas.google.com/g/2005#other" address="person#site.com" primary="true" />
<gd:email rel="http://schemas.google.com/g/2005#home" address="person#gmail.com" />
</entry>
</feed>
Problem
When you do:
xml[1].attributes["id"]
You are getting the text node of <?xml version='1.0' encoding='UTF-8'?> and then trying to get its id attribute. Since it does not exist, you got blank.
Solution
You want:
xml.root.elements['id'].text
#=> user#company.com
Note that "user#company.com" is a text node of the id element. It is not an attribute.

Resources