SOAP , XSL and HTML - xslt

I'm not new with XML request like payments gateways and others.
However i'm new in SOAP and XSL.
I have this XML returned from a rent-a-car web service:
bluealliance-pt.w4.makeitsimple.pt/teste.xml
i want convert it using XSL to show it in my site.
I tried do that with normal XML without any problem at:
bluealliance-pt.w4.makeitsimple.pt/listar.asp
with these files:
bluealliance-pt.w4.makeitsimple.pt/banco.xml
bluealliance-pt.w4.makeitsimple.pt/visualizar.xsl
But i don't know how to do with SOAP XML, how i find elements and values on it.
Is possible clear some info of xml so i can have a shorter XML ?
What is the way to get info from it ?
Hi only need get values from MultiplePrices1 , 2, 3.. etc..
I need that XSL run all MultiPrices and show then all values of each one.
I will appreciate any help

There is nothing special in the provided SOAP response, since the elements of interest are in no namespace.
This simple transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<html>
<table border="1">
<xsl:apply-templates/>
</table>
</html>
</xsl:template>
<xsl:template match="MultiplePrices">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="MultiplePrices/*[not(*)]">
<td><xsl:value-of select="name()"/></td>
<td><xsl:value-of select="."/></td>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
when applied on the XML document contained at the provided URL (http://bluealliance-pt.w4.makeitsimple.pt/teste.xml), produces a table containing a name-value pair for every child element (with simple content) of MultiplePrices.
You can use this XSLT transformation as a base and put inside it your own code.

Related

Is it possible to get all the xPaths of an XSLT file?

Is is possible to get all the xPaths used in an XSLT file?
For example:
XSLT File:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:for-each select="/catalog/cd">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
As output I want a list like this:
/catalog/cd
/catalog/cd/title
/catalog/cd/artist
Maybe by making a custom post processor that outputs a line everytime an xPaths has matched/not been matched?
Ideas are welcome, because I'm very hopeless :)
Thanks!
You can use this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="*">
<xsl:for-each select="ancestor-or-self::*">
<xsl:text>/</xsl:text>
<xsl:value-of select="local-name(.)"/>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
It's difficult because template rule matching in XSLT is very dynamic: if you have a template with match="cities" that calls xsl:apply-templates, and if you have another template with match="city", then the XSLT compiler can't know that there is a path /cities/city.
Internally Saxon has the capability to build a "path map" rather as you describe, and it's used to implement "document projection" in XQuery, but it's of very little use in XSLT because of dynamic template rule despatch.
So static analysis to determine the paths isn't going to get you very far. You also suggest that dynamic analysis - capturing the paths visited at run-time - might also be of interest. In principle you can do that in Saxon with a TraceListener. The difficulty is in determining exactly what you mean by "visited" - for example do you consider xsl:copy-of select="/" as visiting every node in the document, or only the root node?

XSLT: To collect xml files from all folders of name 9000 series using xslt Collection

Please suggest for the 'Collection' function in XSLT to fetch info from 'main.xml' from sub directories names start with 9000 series, i.e.,
D:/Author-Index/9001/main.xml, D:/Author-Index/9002/main.xml, D:/Author-Index/9003/main.xml, D:/Author-Index/9009/main.xml, D:/Author-Index/90nn/main.xml (nth number)
But not from D:/Author-Index/939/main.xml (because three digit folder).
I am getting error using collection('file:///D:/AuthorIndex/9[0-9][0-9][0-9]?select=*main.xml;recurse=yes') to find folder name starts with 9[n][n][n]/main.xml
XML1: D:/Author-Index/9001/main.xml
<article>
<fm>
<title>Journey to Galaxy</title>
<author><snm>Kishan</snm><fnm>TR</fnm></author>
</fm>
<body>
<p>This article explian about Galaxy Journey</p>
</body>
</article>
XML2: D:/Author-Index/9002/main.xml
<article>
<fm>
<title>Journey to Mars</title>
<author><snm>Rudramuni</snm><fnm>TP</fnm></author>
</fm>
<body>
<p>This article explian about Mars Journey</p>
</body>
</article>
XSLT: XSLT version 2
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="varCollection">
<xsl:copy-of select="collection('file:///D:/AuthorIndex/9[0-9][0-9][0-9]?select=*main.xml;recurse=yes')"/>
</xsl:variable>
<xsl:template match="root">
<xsl:for-each select="$varCollection//article">
<xsl:element name="title1"><xsl:value-of select="//fm//title"/></xsl:element>
<xsl:element name="aug">
<xsl:for-each select="//fm//author">
<xsl:element name="au"><xsl:element name="snm"><xsl:value-of select="snm"/></xsl:element><xsl:text> </xsl:text>
<xsl:element name="fnm"><xsl:value-of select="fnm"/></xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Required Result:
<article>
<aug>
<au><snm>Kishan</snm><fnm>TR</fnm></au>
<title1>Journey to Galaxy</title1>
<au><snm>Rudramuni</snm><fnm>TP</fnm></au>
<title1>Journey to Mars</title1>
</aug>
</article>
It is not very efficient, but you could use the collection() function to recursively scan all of the D:/AuthorIndex folders for *main.xml files and then use a predicate filter to select only those documents that are in the 9000 series folders:
<xsl:variable name="varCollection">
<xsl:copy-of
select="collection('file:///D:/AuthorIndex/?select=*main.xml;recurse=yes')
[matches(document-uri(.),'AuthorIndex/9[0-9][0-9][0-9]/.*?main.xml')]"/>
</xsl:variable>
The form of URIs that are accepted by the collection() function varies from product to product. You are using a format that was first introduced in Saxon, and was subsequently adopted by some other products. However, the Saxon implementation certainly doesn't allow the collection URI to be a regular expression like this, and I would be surprised if other implementations do.
The answer is going to be product-specific. In Saxon, you could write your own CollectionURIResolver to handle collection URIs in this form.

Filter data from XSLT

I have a XSL file in which I am creating a field like this:
<ServiceText>
<xsl:value-of select="concat(Yrs,'-',Mos,'-',Days,'-',Hrs)" />
</ServiceText>
The values of 'Yrs,'-',Mos,'-',Days,'-',Hrs , I am receiving from a Web service response and assiging it to the XSL directly. I cannot do any modification to the data in code for these fields, because that is how the ocde is. All data manipulation is on the xslt.
I want to do a data filtering on xslt as follows:
if value of yrs =-1 then yrs=""
if value of mos =-1 then mos=""
if value of Days =-1 then Days=""
if value of Hrs =-1 then Hrs=""
How can I do it on the XSL file?
XSLT 2.0:
<xsl:template match="/root">
<ServiceText>
<xsl:value-of select="string-join((Yrs, Mos, Days, Hrs)[.!=-1],'-')" />
</ServiceText>
</xsl:template>
See link for a Working example
In XSLT 1.0 use something like this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*/*[not(.= -1)]">
<xsl:value-of select="concat(., substring('-', 2 - not(self::Hrs)))"/>
</xsl:template>
<xsl:template match="*/*[. = -1]"/>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>
<Yrs>-1</Yrs>
<Mos>7</Mos>
<Days>15</Days>
<Hrs>3</Hrs>
</t>
the wanted result is produced:
7-15-3
Do Note:
It seems that there is an assumption that the "-1" values form a contiguous group (right to left in the sequence Yrs, Mos,Days).
If this assumption is violated, it would be impossible to understand what is the missing part in 2013-10-8 -- is it the months or the days ?

XML namespace reference in XSL stylesheet problem

I am trying to extract data out of the following XML fragment:
<?xml version= "1.0" ?>
<Stmts xmlns="http://tempuri.org/Statement.xsd" Generation="2011-08-01T12:41:41" >
<StatementDetail AccountStatus="Open" CompanyID="" TransactionCount="182" >
<Transactions>
<Manual.../>
...
</Transactions>
</StatementDetail>
</Stmts>
Notice that the element has a xmlns attribute.
When I try to use the following XSL I get no data.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>CabCharge</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Batch</th>
<th>TransNo</th>
</tr>
<xsl:for-each select="Stmt/StatementDetail/Transactions/Manual">
<tr>
<td><xsl:value-of select="#Batch"/></td>
<td><xsl:value-of select="#TransNo"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
BUT! If I remove the XMLNS attribute from the element, I do get data.
What do I need to specifiy in the XSL to recognise the namespace???
Thanks.
Make sure to declare the default namespace of the document in your stylesheet, like:
<xsl:stylesheet version="1.0"
xmlns="http://tempuri.org/Statement.xsd"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Otherwise the XSLT processor will consider the elements referenced in your stylesheet as belonging to default namespace null.
Moreover, if you want the namespace exlcuded from the output document, you need to declare null namespace for the root literal element html, like:
<xsl:template match="/">
<html xmlns="">
<!-- your stuff -->
</html>
</xsl:template>
Do note also that:
In the xsl:for-each you are selecting the wrong element (Stmt in place of Stmts)
The attributes Batch and TransNo do not exist in your input documents.

XSL 101 - How to generate a basic XSL style sheet for a given XML document?

Below is a snippet of what you get when you save the configuration of IIS 6/Windows Server 2003 web sites to a file:
<?xml version ="1.0"?>
<configuration xmlns="urn:microsoft-catalog:XML_Metabase_V64_0">
<MBProperty>
<IIsWebServer Location ="/LM/W3SVC/1"
AppPoolId="DefaultAppPool"
DefaultDoc="Default.htm,Default.asp,index.htm,iisstart.htm,Default.aspx"
ServerAutoStart="FALSE"
ServerBindings=":80:"
ServerComment="Default Web Site"
ServerSize="1"
>
</IIsWebServer>
<IIsWebServer Location ="/LM/W3SVC/1020944513"
AuthFlags="0"
LogPluginClsid="{FF160663-DE82-11CF-BC0A-00AA006111E0}"
ServerAutoStart="TRUE"
ServerBindings="161.230.8.183:80:"
ServerComment="staging.magazinefundraising.com"
>
</IIsWebServer>
<IIsWebServer Location ="/LM/W3SVC/103632312"
AuthFlags="0"
LogPluginClsid="{FF160663-DE82-11CF-BC0A-00AA006111E0}"
ServerAutoStart="TRUE"
ServerBindings="161.230.9.48:80:"
ServerComment="QSP2.Downtime"
>
</IIsWebServer>
</MBProperty>
</configuration>
As you can see, there are multiple <IIsWebServer> sections between the <MBProperty> and </MBProperty> elements.
I'd like to create a simple xsl stylesheet which outputs a multi-column (tabular) result containing the following attributes for each IIsWebServer instance:
ServerComment
ServerBindings
AuthFlags
So the result might look something like:
ServerComment ServerBindings AuthFlags
------------- -------------- ---------
QSP2.Downtime 161.230.9.48:80: 0
and so on...
Thanks!
XSL could be something like this:
<?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"
xmlns:mb="urn:microsoft-catalog:XML_Metabase_V64_0"
exclude-result-prefixes="msxsl">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
ServerComment   ServerBindings   AuthFlags
<xsl:apply-templates />
</xsl:template>
<xsl:template match="mb:IIsWebServer">
<xsl:value-of select="./#ServerComment" />
<xsl:text> </xsl:text>
<xsl:value-of select="./#ServerBindings" />
<xsl:text> </xsl:text>
<xsl:value-of select="./#AuthFlags" />
</xsl:template>
</xsl:stylesheet>
OF course, you'll want to prettify it :-) but it basically works.
Whether it's the right choice and best technology to use for this, is totally up to you :-) But it can be done - no problem.
Marc
As Emil said, XSL isn't exactly made for text formatting. However, you should be able to achieve your goal if you output HTML. Something like the following:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table>
<tr>
<th>ServerComment</th>
<th>ServerBindings</th>
<th>AuthFlags</th>
</tr>
<xsl:for-each select="/configuration/MBProperty/IIsWebServer">
<tr>
<td><xsl:value-of select="#ServerComment" /></td>
<td><xsl:value-of select="#ServerBindings" /></td>
<td><xsl:value-of select="#AuthFlags" /></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
If you're going for developing a tabular display for viewing purposes only, this may be your best bet. However, if you're planning on using the data in another way, it may be better to go with Marc or Emil's approach.