I am trying to modify the xsl code to apply some font size and color to the content it produces but not having much success.
This is my sample xml data format
<xml>
<Node1 attribute1="Test1" attribute2="Test2" attribute3="Test3"></Node1>
</xml>
and here is the current xsl template that I have:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:jscript="http://www.url.com">
<xsl:apply-templates select="//Node1"></xsl:apply-templates>
<xsl:template match="Node1">
Value# 1 = <xsl:value-of select="#attribute1"/>
Value# 2 = <xsl:value-of select="#attribute2"/>
Value# 3 = <xsl:value-of select="#attribute3"/>
</xsl:template>
</xsl:stylesheet>
I would like to display the content
Value #1 = Test1
Value #2 = Test2
Value #3 = Test3
with some font style and color on the content. Can someone please provide some example how can I do that? Thank you
Related
I'm looking for the best way to get all unique (no duplicates) nested nodes of all sibling nodes. The node I'm am interested in is "Gases". The sibling nodes are "Content". My simplified XML:
<Collection>
<Content>
<Html>
<root>
<Gases>NO2</Gases>
<Gases>CH4</Gases>
<Gases>O2</Gases>
</root>
</Html>
</Content>
<Content>
<Html>
<root>
<Gases>NO2</Gases>
<Gases>CH4</Gases>
<Gases>CO</Gases>
<Gases>LEL</Gases>
<Gases>NH3</Gases>
</root>
</Html>
</Content>
</Collection>
Desired result: NO2 CH4 O2 CO LEL NH3
I'm new to XSLT so any help would be much appreciated. I've been trying to use XPATH, similar to here, but with no luck.
This XSLT stylesheet will produce the desired output. Note that it relies on there being no duplicate Gases element inside a single Content element.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<!-- Match Gases elements whose value does not appear in a Gases element inside a previous
Content element. -->
<xsl:template match="//Gases[not(. = ancestor::Content/preceding-sibling::Content//Gases)]">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:template>
<!-- Need to override the built-in template for text nodes, otherwise they will still get
printed out. -->
<xsl:template match="text()"/>
</xsl:stylesheet>
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 ?
I am transforming XML into HTML using XSLT.
I have the following XML structure:
<root>
<element>
<subelement>
This is some html text which should be <span class="highlight">displayed highlighted</span>.
</subelement>
</element>
</root>
I use the following template for the transformation:
<xsl:template name="subelement">
<xsl:value-of select="." />
</xsl:template>
Unfortunately, I lose the <span>-tags.
Is there a way to keep them so the HTML is displayed correctly (highlighted)?
The correct way to get the all the contents of the current matching node (text nodes included) is:
<xsl:template match="subelement">
<xsl:copy-of select="node()"/>
</xsl:template>
This will copy everything descendent.
Try using <xsl:copy-of... instead of <xsl:value-of... for example:
<xsl:template name="subelement">
<xsl:copy-of select="*" />
</xsl:template>
Note the * which will stop the <subelement></subelement> bits being output to the results, rather than using . which will include the <subelement></subelement> bits .
For example, the xsl stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="root/element">
<output>
<xsl:apply-templates select="subelement"/>
</output>
</xsl:template>
<xsl:template match="subelement">
<xsl:copy-of select="*"/>
</xsl:template>
</xsl:stylesheet>
when applied to your example xml file returns:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<span class="highlight">displayed highlighted</span>
</output>
The <xsl:value-of> declaration takes the concatenated contents of all text nodes within the element, in sequential order, and doesn't output any elements at all.
I'd recommend using <xsl:apply-templates> instead. Where it finds a text node, it will output the contents as-is, but you would need to define a template for handling span tags to convert them to html ones. If that span tag IS an html tag, then strictly speaking, you should have separate namespaces for your own document structure and html.
I have an XML file that I am transforming via XSLT. I am passing an XML as parameter to the XSLT via C#. The parameter's name is attachment and it contains XML. It is written as follows:
StringWriter sw = new StringWriter();
XmlTextWriter w = new XmlTextWriter(sw);
w.WriteStartElement("root");
if (!string.IsNullOrEmpty(sWordFileName)) {
w.WriteStartElement("mylink", sWordFileName);
w.WriteEndElement();
}
if (!string.IsNullOrEmpty(sPDFFileName)) {
w.WriteStartElement("mylink", sPDFFileName);
w.WriteEndElement();
}
w.Close();
XPathDocument doc = new XPathDocument(new StringReader(sw.ToString()));
XPathNavigator nav = doc.CreateNavigator();
_exportSet[currentExportSet].Format.ParamList["attachment"] = nav.Select("./*");
My xml parameter looks like
<root><attachment xmlns=file1><attachment xmlns=file2></root>
Now in XSLT I need to iterate through this XML param and create a link.
Here is my XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:my-scripts="urn:my-scripts"
xmlns="factiva.com/fcs/schemas/newsSummaries">
<xsl:param name="attachment"/>
<xsl:for-each select="$attachment">
<a target="_blank" href="#"><xsl:copy-of select="."/></a>
</xsl:for-each>
</xsl:stylesheet>
But it doesn't create a link.
An XSLT parameter is different than an XML tag name. Parameters are passed using the tag as described here.
As stated in the comments below, this problem is not too different from what is provided in the link above.
StringWriter sw = new StringWriter();
XmlTextWriter w = new XmlTextWriter(sw);
w.WriteStartElement("root");
if (!string.IsNullOrEmpty(sWordFileName)) {
w.WriteStartElement("attachment", sWordFileName);
w.WriteAttributeString("name", sWordFileName);
w.WriteEndElement();
}
if (!string.IsNullOrEmpty(sPDFFileName)) {
w.WriteStartElement("attachment");
w.WriteAttributeString("name", sPDFFileName);
w.WriteEndElement();
}
w.WriteEndElement();
w.Close();
XPathDocument doc = new XPathDocument(new StringReader(sw.ToString()));
XPathNavigator nav = doc.CreateNavigator();
XsltArgumentList xslArg = new XsltArgumentList();
xslArg.AddParam("attachment","",nav);
Here would be XSL to match per Accessing parameters which contain mark-up:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:my-scripts="urn:my-scripts"
xmlns="factiva.com/fcs/schemas/newsSummaries">
<xsl:param name="attachment" />
<xsl:template match="/">
<xsl:apply-templates select="$attachment"/>
</xsl:template>
<xsl:template match="attachment">
<a target="_blank" href="{#name}">{#name}</a>
</xsl:template>
</xsl:stylesheet>
You can pass any XPath/XSLT data type as parameters. How to do that entirely depends on the XSLT processor implementation.
As proof this stylesheet, with any input (not used):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="attachment" select="document('parameter.xml')/root"/>
<xsl:template match="/">
<xsl:apply-templates select="$attachment"/>
</xsl:template>
<xsl:template match="attachment">
<a target="_blank" href="{#href}">Link</a>
</xsl:template>
</xsl:stylesheet>
And parameter.xml resource as:
<root>
<attachment href="file1"/>
<attachment href="file2"/>
</root>
Output:
<a target="_blank" href="file1">Link</a>
<a target="_blank" href="file2">Link</a>
It should read <xsl:for-each select="attachment">.... There is no $ sign because attachment is the name of an XML element, not a variable.
EDIT after you've given the full XSLT and XML.
There are several problems with your XML:
All tags should be closed.
You may not use the xmlns for anything else that it's meant for — namespaces.
You must have double quotes around the attribute values
So a correct version of the XML file would be (for instance):
<root>
<attachment ptr="file1" />
<attachment ptr="file2" />
</root>
The XSLT file has some issues too:
The xsl namespace should be bound to the exact URI http://www.w3.org/1999/XSL/Transform.
You must have at least a template so that the XSLT transform processes your input XML document.
A correct version would be, for instance:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<xsl:for-each select="attachment">
<a target="_blank" href="{#ptr}"><xsl:value-of select="#ptr" /></a>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I'm not sure it is exactly what you want, but for the above document it produces the following fragment:
<a target="_blank" href="file1">file1</a>
<a target="_blank" href="file2">file2</a>
You would want to put the value of your attribute that has the link in it like so:
<xsl:value-of select="#YourAttribute"/>
This selects an attribute for the current xml element.
The code you posted is somewhat incorrect. Where are the quotes, what is $attachment?
You probably forgot to mention namespace, to select correctly, you need to write select="//file1:attachment" or sth like that.
I have a specific problem getting values for width and height out of some XML that has namespace prefixes defined. I can get other values such as SomeText from RelatedMaterial quite easily using normal xpath with namespace "n:" but unable to get values for width and height.
Sample XML:
<Description>
<Information>
<GroupInformation xml:lang="en">
<BasicDescription>
<RelatedMaterial>
<SomeText>Hello</SomeText>
<t:ContentProperties>
<t:ContentAttributes>
<t:Width>555</t:Width>
<t:Height>444</t:Height>
</t:ContentAttributes>
</t:ContentProperties>
</RelatedMaterial>
</BasicDescription>
</GroupInformation>
</Information>
</Description>
Here is an extract from the XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:n="urn:t:myfoo:2010" xmlns:tva2="urn:t:myfoo:extended:2008"
<xsl:apply-templates select="n:Description/n:Information/n:GroupInformation"/>
<xsl:template match="n:GroupInformation">
<width>
<xsl:value-of select="n:BasicDescription/n:RelatedMaterial/t:ContentProperties/t:ContentAttributes/t:Width"/>
</width>
</xsl:template>
The above XSLT does not work for getting the width. Any ideas?
I'm not sure you have realised that both your input and XSLT is invalid, it's always better to provide working examples.
Anyway, if we look at the XPath expression n:BasicDescription/n:RelatedMaterial/t:ContentProperties/t:ContentAttributes/t:Width you're using a prefix n which is mapped to urn:t:myfoo:2010 but when the data infact is in the default namespace. The same goes for the t prefix which isn't defined at all in neither the input data nor XSLT.
You need to define the namespaces on "both sides", in the XML data and the XSLT transformation and they need to be the same, not the prefixes, but the URI.
Somebody else could probably explain this better than me.
I've corrected your example and added a few things to make this work.
Input:
<?xml version="1.0" encoding="UTF-8"?>
<Description
xmlns="urn:t:myfoo:2010"
xmlns:t="something...">
<Information>
<GroupInformation xml:lang="en">
<BasicDescription>
<RelatedMaterial>
<SomeText>Hello</SomeText>
<t:ContentProperties>
<t:ContentAttributes>
<t:Width>555</t:Width>
<t:Height>444</t:Height>
</t:ContentAttributes>
</t:ContentProperties>
</RelatedMaterial>
</BasicDescription>
</GroupInformation>
</Information>
</Description>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:n="urn:t:myfoo:2010"
xmlns:t="something...">
<xsl:template match="/">
<xsl:apply-templates select="n:Description/n:Information/n:GroupInformation"/>
</xsl:template>
<xsl:template match="n:GroupInformation">
<xsl:element name="width">
<xsl:value-of select="n:BasicDescription/n:RelatedMaterial/t:ContentProperties/t:ContentAttributes/t:Width"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<width>555</width>