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.
Related
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?
I'm a beginning user of xslt and xpath. Using an xpath on a command line (Ubuntu 14.04) with a xml file works, but the very same xpath in an xslt file returns nothing. I'm working with Juniper Junos xml files. Any suggestions?
Thanks,
George
The xml file begins with:
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/12.3R8/junos">
<interface-information xmlns="http://xml.juniper.net/junos/12.3R8/junos-interface" junos:style="normal">
<physical-interface>
<name>fe-0/1/0</name>
<logical-interface>
<name>fe-0/1/0.0</name>
...
The command line that works in Ubuntu 14.04 is:
xpath -e "/rpc-reply/interface-information/physical-interface/logical-interface/name" interfaces.xml
The xslt file is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Interfaces</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Name</th>
</tr>
<xsl:for-each select="/rpc-reply/interface-information/physical-interface/logical-interface">
<tr>
<td><xsl:value-of select="name"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The problem here is quite simple. You are not using namespaces in your XPaths. Apparently your command line utility doesn't care, or evaluates XPaths based on the elements' QNames ignores default namespaces and does some other non-standard handling of namespaces as well.
The solution:
Declare prefixes at the top of your stylesheet:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:nbase="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:junosi="http://xml.juniper.net/junos/12.3R8/junos-interface"
>
use those prefixes in your XPaths:
<xsl:for-each select="/nbase:rpc-reply/junosi:interface-information
/junosi:physical-interface/junosi:logical-interface">
<tr>
<td><xsl:value-of select="junosi:name"/></td>
</tr>
</xsl:for-each>
I'm trying to retrieve a certain value from an XML document and output that value into a new XML document - the source XML is full of unused data, I only need the specific part.
Source XML :-
<dpp:Programme xmlns:dpp="http://www.digitalproductionpartnership.co.uk/ns/as11/2012" xmlns:itv="http://dpp.itv.com/timecodes/v1">
<dpp:Editorial>
<dpp:SeriesTitle>test</dpp:SeriesTitle>
<dpp:ProgrammeTitle>test</dpp:ProgrammeTitle>
<dpp:EpisodeTitleNumber>test</dpp:EpisodeTitleNumber>
<dpp:ProductionNumber>2/1993/0022#001</dpp:ProductionNumber>
<dpp:Synopsis>None</dpp:Synopsis>
<dpp:Originator>None</dpp:Originator>
<dpp:CopyrightYear>2013</dpp:CopyrightYear>
</dpp:Editorial>
<dpp:Technical>
<dpp:ShimName>UK DPP HD</dpp:ShimName>
<dpp:Video>
<dpp:VideoBitRate unit="Mbps">100</dpp:VideoBitRate>
<dpp:VideoCodec>AVCI</dpp:VideoCodec>
<dpp:VideoCodecParameters>High 4:2:2 level 4.1</dpp:VideoCodecParameters>
<dpp:PictureFormat>1080i50 16:9</dpp:PictureFormat>
<dpp:AFD>10</dpp:AFD>
<dpp:PictureRatio>16:9</dpp:PictureRatio>
<dpp:ThreeD>false</dpp:ThreeD>
<dpp:ProductPlacement>false</dpp:ProductPlacement>
<dpp:FPAPass>Not tested</dpp:FPAPass>
</dpp:Video>
<dpp:Audio>
<dpp:AudioSamplingFrequency unit="kHz">48</dpp:AudioSamplingFrequency>
<dpp:AudioBitDepth>24</dpp:AudioBitDepth>
<dpp:AudioCodecParameters>PCM</dpp:AudioCodecParameters>
<dpp:AudioTrackLayout>EBU R 123: 4b</dpp:AudioTrackLayout>
<dpp:PrimaryAudioLanguage>eng</dpp:PrimaryAudioLanguage>
<dpp:SecondaryAudioLanguage>zxx</dpp:SecondaryAudioLanguage>
<dpp:TertiaryAudioLanguage>eng</dpp:TertiaryAudioLanguage>
<dpp:AudioLoudnessStandard>EBU R 128</dpp:AudioLoudnessStandard>
</dpp:Audio>
<dpp:Timecodes>
<dpp:LineUpStart>09:58:00:00</dpp:LineUpStart>
<dpp:IdentClockStart>09:59:20:00</dpp:IdentClockStart>
<dpp:Parts>
<dpp:Part>
<dpp:PartNumber>1</dpp:PartNumber>
<dpp:PartTotal>1</dpp:PartTotal>
<dpp:PartSOM>10:30:41:11</dpp:PartSOM>
<dpp:PartDuration>00:00:30:13</dpp:PartDuration>
</dpp:Part>
</dpp:Parts>
<dpp:TotalNumberOfParts>1</dpp:TotalNumberOfParts>
<dpp:TotalProgrammeDuration>00:00:30:13</dpp:TotalProgrammeDuration>
</dpp:Timecodes>
<dpp:AccessServices>
<dpp:AudioDescriptionPresent>false</dpp:AudioDescriptionPresent>
<dpp:ClosedCaptionsPresent>false</dpp:ClosedCaptionsPresent>
<dpp:OpenCaptionsPresent>false</dpp:OpenCaptionsPresent>
<dpp:SigningPresent>No</dpp:SigningPresent>
</dpp:AccessServices>
<dpp:Additional>
<dpp:CompletionDate>2014-01-07</dpp:CompletionDate>
<dpp:TextlessElementExist>false</dpp:TextlessElementExist>
<dpp:ProgrammeHasText>true</dpp:ProgrammeHasText>
<dpp:ProgrammeTextLanguage>eng</dpp:ProgrammeTextLanguage>
<dpp:AssociatedMediaFilename>2-1993-0022-001.mxf</dpp:AssociatedMediaFilename>
<dpp:MediaChecksumType>MD5</dpp:MediaChecksumType>
<dpp:MediaChecksumValue>6154fd9cf312492e2dea68bee656ded7</dpp:MediaChecksumValue>
</dpp:Additional>
<dpp:ContactInformation>
<dpp:ContactEmail>None</dpp:ContactEmail>
<dpp:ContactTelephoneNumber>None</dpp:ContactTelephoneNumber>
</dpp:ContactInformation>
</dpp:Technical>
<itv:AdditionalTimeCodes>
<itv:Element>
<itv:ElementType>Essence</itv:ElementType>
<itv:ElementSOM>10:30:41:11</itv:ElementSOM>
<itv:Duration>00:00:30:13</itv:Duration>
<itv:Fade>false</itv:Fade>
<itv:Mix>false</itv:Mix>
<itv:Property>Essence</itv:Property>
</itv:Element>
</itv:AdditionalTimeCodes>
</dpp:Programme>
This is the XSL I have created :-
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="Programme/Technical/Timecodes">
<tr>
<td>
<xsl:value-of select="TotalProgrammeDuration"/>
</td>
</tr>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
But all I'm getting returned is a blank page?
All I need is the timecode value (TotalProgrammeDuration) from Programme/Technical/Timecodes
What am I doing wrong? (I'm very new to this - if you can't rell already)
J.
The elements in your input XML have a namespace. You need to declare this namespace in your XSLT stylesheet too - and prefix any element names you mention.
Namespaces are an important concept in XSLT (as with XML technologies in general) so I recommend you spend some time understanding the basics. For instance, start with a previous answer of mine.
Stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dpp="http://www.digitalproductionpartnership.co.uk/ns/as11/2012">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="dpp:Programme/dpp:Technical/dpp:Timecodes">
<tr>
<td>
<xsl:value-of select="dpp:TotalProgrammeDuration"/>
</td>
</tr>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Also note that you are obviously outputting XHTML. Then, it makes more sense to set
<xsl:output method="text">
to
<xsl:output method="html">
Further, indent="yes" only makes sense when used with html, not with text.
Below is a second attempt at writing your stylesheet that uses separate templates (which is generally a better idea than using xsl:for-each).
Stylesheet (a better approach)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dpp="http://www.digitalproductionpartnership.co.uk/ns/as11/2012">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="dpp:Timecodes">
<tr>
<td>
<xsl:value-of select="dpp:TotalProgrammeDuration"/>
</td>
</tr>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
Output
<html xmlns:dpp="http://www.digitalproductionpartnership.co.uk/ns/as11/2012">
<body>
<tr>
<td>00:00:30:13</td>
</tr>
</body>
</html>
You are missing namespace declarations:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dpp="http://www.digitalproductionpartnership.co.uk/ns/as11/2012" exclude-result-prefixes="dpp">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="dpp:Programme/dpp:Technical/dpp:Timecodes">
<tr>
<td>
<xsl:value-of select="dpp:TotalProgrammeDuration"/>
</td>
</tr>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
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.
I'm new to XSLT. I'm trying to change the font size of a specific text in XML file using XSLT. For eg- I have the CDCatalog.xml file with following data.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="cdcat.xsl"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist><SmallText>Bob Dylan</SmallText><LineBreak/>*</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
</catalog>
and the cdCat.XSL file is-
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:include href="cdCatalog.xsl" /> <!-- I added this -->
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th align="left">Title</th>
<th align="left">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>
I added a new xsl file cdCatalog.XSL file with following details-
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="LineBreak">
<br/>
</xsl:template>
<xsl:template match="Superscript">
<sup>
<xsl:value-of select="."/>
</sup>
</xsl:template>
<xsl:template match="SmallText">
<font size="1">
<xsl:value-of select="."/>
</font>
</xsl:template>
</xsl:stylesheet>
and included this file in the CDCat.xsl file.and added the tags - <smallText>, <LineBreak> in the CdCatalog.xml file. now when I open the xml file i dont see the LineBreak nor the font size difference. Can anyone please suggest if I'm missing something.
Thanks in advance
Sai
You need to use apply-templates to indicate where your template matches should take effect.
XML says nothing about presentation, that's the whole point. It's a data format.
If you want your XSLT to output to something where presentation matters I suggest you transform to HTML and get let HTML/CSS handle the styling.
Having seen your actual code now (hint: use the formatting when creating questions) don't use the font tag. What you want semantically and in practice is just headers <h1>, <h2>, <h3> etc, and I'd still suggest you add a CSS link in there. Oh and <xsl:output method="html" />
In-between these two opening tags:
<html>
<body>
...I'd place a link to a style sheet that defines the font sizes. Alternatively (and useful if you want a self contained HTML file to email around) you could put a style block there instead.