how to do template not matching using xslt 1.0 - xslt

I have an requirement in which I am processing the message based on the root element tag and for that I have created 3 different template match based on the root tag element. I was wondering how to process the message if the client is sending different message which is not matching the root tag element.
Input:
<?xml version="1.0"?>
<process1 xmlns="http://www.openapplications.org/oagis/10" systemEnvironmentCode="Production" languageCode="en-US">
<Appdata>
<Sender>
</Sender>
<Receiver>
</Receiver>
<CreationDateTime/>
</Appdata>
</process1>
2nd message: Everything will be same except root tag will be process2, process3
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/*[local-name()='proces1']">
<operation>dosomthing</operation>
</xsl:template>
<xsl:template match="/*[local-name()='process2']">
<operation>dosomthing2</operation>
</xsl:template>
<xsl:template match="/*[local-name()='process2']">
<operation>blah blah</operation>
</xsl:template>
</xsl:stylesheet>
My question here is I want to process message in case if it's not matching the 3 templates process1,process2,process3.
Can anyone please give advise how to achieve that?

First off, don't use local-name(). It's easy to declare and use the proper namespace, do it.
Secondly, just make a template that is less specific to catch any document element with a name that you did not anticipate (see the 4th template below):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:oagis="http://www.openapplications.org/oagis/10"
>
<xsl:template match="/oagis:process1">
<operation>dosomething1</operation>
</xsl:template>
<xsl:template match="/oagis:process2">
<operation>dosomething2</operation>
</xsl:template>
<xsl:template match="/oagis:process3">
<operation>dosomething3</operation>
</xsl:template>
<xsl:template match="/*" priority="0">
<!-- any document element not mentioned above -->
</xsl:template>
</xsl:stylesheet>
Note: If the first three templates all do the same, you can collapse them into one.
<xsl:template match="/oagis:process1|/oagis:process2|/oagis:process3">
<operation>dosomething</operation>
</xsl:template>

Related

XSLT: How to discard unwanted HTML nodes from source?

I am using XSLT 1.0, and using xsltproc on OS X Yosemite.
The source content is HTML; the target content is XML.
The issue is a fairly common one. I want all "uninteresting"
nodes simply to be discarded from the output. I've seen catch-all
directives like this:
<xsl:template match="node()|script"/>
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
This is close to what I need. But unfortunately, it's too strong when I need to add another template that visits one of the text nodes caught by node(). For example, suppose I added this template:
<xsl:template match="a/div[#class='location']/br">
<xsl:text> </xsl:text>
</xsl:template>
which simply replaces certain <br/> elements with spaces.
Well, node() precludes this latter template from taking effect,
because the relevant text node containing the line-break is discarded
already!
Well, to correct the issue, here's what I have done in lieu of the catch-all node():
<xsl:template match="html/head|div[#id='banner_parent']|button|ul|div[#id='feed_title']|span|div[#class='submit_event']|script"/>
But this is precisely the problem: I am now piecing together a template
whose matching criteria is likely to be error-prone when the source
content changes.
Is there a simpler directive that would accomplish the same thing? I'm aiming for something like this:
<xsl:template match="node()[not(locations)]|script"/>
Thanks.
If i understood correctly, you want only some nodes in the output and the rest you dont care abour, in this example I try to catch only li elements and throw the rest away.. not sure if this is what you want though http://xsltransform.net/gWmuiKk
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<!-- Lets pretend li is interesting for you -->
<xsl:template match="li">
<xsl:text>Interesting Node Only!
</xsl:text>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:apply-templates select="#*|node()"/>
</xsl:template>
</xsl:transform>

with xslt how do I use choose/when to remove elements from document

Here is my example document
<a >
<b flag='foo'>
<c/>
<d/>
</b>
</a>
I am looking to remove the "c" element only when the flag attribute on b is 'bar'.
Ie if flag='foo' the "c" element should not be removed. I do not currently have an xsl debugging tool on my pc, and have been unable to find an online tool that shows xslt error information, and have been running the following test xsl transform on http://xslttest.appspot.com/ :
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes" version="1.0" encoding="ISO-8859-1"/>
<!--Identity template to copy all content by default-->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:choose>
<xsl:when test="/a/b[#flag='bar']">
<xsl:template match="/a/b/c"/>
</xsl:when>
</xsl:choose>
</xsl:stylesheet>
When I run this I get Error: Failed to compile stylesheet. 3 errors detected.
I'm looking for help (1) fixing the problems with the xsl code and (2) anything out there like jsfiddle for xsl that can debug/test fragements of xsl code.
You can't put a choose outside a template, but you don't need to - you can use predicates in match expressions so just declare your no-op template to match the elements you want to remove:
<xsl:template match="b[#flag='bar']/c" />
or more generally, if the parent of the c element might have various names
<xsl:template match="c[../#flag='bar']" />
or
<xsl:template match="*[#flag='bar']/c" />

Problems with XSLT and apply templates

I'm going to be brief. I'm doing XSLT on the client. The output is a report/html with data. The report consists of several blocks, ie one block is one child element of root-node in the xml file.
There are n reports residing in n different xslt-files in my project and the reports can have the same block. That means if there is a problem with one block for one report and it is in n reports i have to update every n report (xslt file).
So i want to put all my blocks in templates (kind-of-a businesslayer) that i can reuse for my reports by xsl:include on the templates for those reports.
So the pseudo is something like this:
<?xml version="1.0".....?>
<xsl:stylesheet version="1.0"....>
<xsl:include href="../../Blocks/MyBlock.xslt"/>
<xsl:template match='/'>
<xsl:apply-templates />
</xsl:template>
</xsl:stylesheet>
MyBlock.xslt:
<?xml version="1.0"....?>
<xsl:stylesheet version="1.0".....>
<xsl:template match='/root/rating'>
HTML OUTPUT
</xsl:template>
</xsl:stylesheet>
I hope someone out there understands my question. I need pointers on how to go about this, if this is one way to do it. But it doesn't seem to work.
Below is my experience that how am dealing this.
This is example which I modified your code.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0">
<xsl:include href="../../Blocks/MyBlock.xslt"/>
<xsl:template match="/">
<xsl:apply-templates select="node()" mode="callingNode1"/>
</xsl:template>
</xsl:stylesheet>
MyBlock.xslt:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0">
<xsl:template mode="callingNode1" match="*">
HTML OUTPUT
</xsl:template>
<xsl:template mode="callingNode2" match="/root/rating">
HTML OUTPUT
</xsl:template>
</xsl:stylesheet>
Here am calling the nodes based on the mode & match.

XSLT: Match all elements of a namespace except one element

I want to write an XSLT template that matches all elements of one namespace except one element. For example I want to match all elements foo:*, but not foo:bar.
Is that possible to define this in a selector or do I have to write an xsl:if condition within the xsl:template (and how can I test the local name of the element)?
To do this, you can just have a template that matches foo:bar that does nothing with it like so:
<xsl:template match="foo:bar" />
To match other foo elements, you can use a more general template
The XSLT processor should match the more specific template first, and so foo:bar will be ignored, and all other foo elements matched by the other template.
So, for example, given this input XML
<foo:root xmlns:foo="foo.com">
<foo:bar>No match</foo:bar>
<foo:pie>Match</foo:pie>
</foo:root>
When you apply the following XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:foo="foo.com">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="foo:bar" />
<xsl:template match="foo:*">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If you wanted to do different processing on foo:bar, just add code to the relevant template.
The following is output, without any sign of foo:bar
<foo:root xmlns:foo="foo.com">
<foo:pie>Match</foo:pie>
</foo:root>
XSLT 1.0:
<xsl:template match="foo:*[not(local-name()='bar')]">
<!--do stuff-->
</xsl:template>
XSLT 2.0:
<xsl:template match="foo:*[. except self::foo:bar]">
<!--do stuff-->
</xsl:template>

How to copy all child nodes of any type of a template context element

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.