We help IT Professionals succeed at work.

Apply multiple xsl match template on a xml

enthuguy
enthuguy asked
on
Hi friends, I'm new to XML/XSLT...can you help as usual please

Scenario is, I have several xml files where I need to remove certain sections based on the value I specify. Basically to appply multiple xslt templates on a XML document.

please check the attached sample xml and below xslt document (I couldnt attach it)
sample.xml: contains 4 sections.
testone.xslt: Has got one template to remove "First" section. this works fine.
testtwo.xslt: Has got two templates to remove "First" and "Third" section. this isnt working as expected.

I was trying to apply multiple templates on a single document in one go.

thanks in advance.

testone.xslt
============
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:ns1="urn:/crmondemand/xml/fieldmanagement/data"
exclude-result-prefixes="ns1">
 <xsl:param name="testParam"/>
<xsl:output method="xml" indent="yes" />
      <xsl:template match="@*|node()" >
          <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
          </xsl:copy>
      </xsl:template>
      
      <xsl:template match="ns1:ListOfFields/ns1:Field">
        <xsl:choose>
            <xsl:when test="ns1:ListOfFieldTranslations/ns1:FieldTranslation[starts-with(ns1:DisplayName, 'First')]">
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>  
      </xsl:template>
</xsl:stylesheet>



testtwo.xslt
============
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:ns1="urn:/crmondemand/xml/fieldmanagement/data"
exclude-result-prefixes="ns1">
 <xsl:param name="testParam"/>
<xsl:output method="xml" indent="yes" />
      <xsl:template match="@*|node()" >
          <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
          </xsl:copy>
      </xsl:template>
      
      <xsl:template match="ns1:ListOfFields/ns1:Field">
        <xsl:choose>
            <xsl:when test="ns1:ListOfFieldTranslations/ns1:FieldTranslation[starts-with(ns1:DisplayName, 'First')]">
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>  
      </xsl:template>
        
        <xsl:template match="ns1:ListOfFields/ns1:Field">
        <xsl:choose>
            <xsl:when test="ns1:ListOfFieldTranslations/ns1:FieldTranslation[starts-with(ns1:DisplayName, 'Third')]">
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*|node()" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>  
      </xsl:template>
</xsl:stylesheet>
sample.xml
Comment
Watch Question

Pravin AsarPrincipal Systems Engineer
CERTIFIED EXPERT
Top Expert 2005

Commented:
// Get All filenames. In the example

string MyXmlPath = Request.PhysicalApplicationPath + "\\MyXmlData.xml";

// Xslt
string MyXsltPath = Request.PhysicalApplicationPath + "\\MyXmlDataTransoform.xslt";

// Now create an instance of the XPathDocument class and store in there the XML document
XPathDocument xmlDoc = new XPathDocument(MyXmlPath);

// Now create an instance of the XslCompiledTransform class that we will use to transform the XML data using an XSLT stylesheet
XslCompiledTransform XSLTransform = new XslCompiledTransform();
XSLTransform.Load(MyXsltPath);

// Then execute the transform and output the results.

XSLTransform.Transform(MyXmlPath, null, Response.Output);  

Do not forget to add these namespaces in the Default.aspx.cs file

using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;


 
Run your application and see the MyXmlData's related data (transformed by the XLST file) being displayed in the screen.



If you want the transformation results to be saved to an .htm file you must ,

1. comment out this line of code

// XSLTransform.Transform(MyXmlPath, null, Response.Output);  


2. Add another item to your site, an .htm file. Name it MyHtmlPage.htm.

iii) Add these lines of code to the  Page_Load routine.

string MyHTMLPath = Request.PhysicalApplicationPath + "\\MyHtmlPage.htm";
 
XSLTransform.Transform(MyXmlPath, MyHTMLPath);
 
Run your application and see the MyXmlData's related data (transformed by the XLST file) being written into the html file.Open the MyHtmlPage.htm file

Author

Commented:
thanks pravin for helping out. unfortunately, I'm not a .net or java person and I cannot use those. sorry.

I was using below online xslt tester to get my result. Later I might integrate with ANT and/or vbscript (when using vbscript I was using microsoft command line util "msxsl.exe")

http://xslttest.appspot.com/

please help if you can
Pravin AsarPrincipal Systems Engineer
CERTIFIED EXPERT
Top Expert 2005

Commented:
Since it was posted under ASP.NET/Java topics, I thought so.

Author

Commented:
I've requested that this question be deleted for the following reason:

not response. please delete
Gertone (Geert Bormans)Information Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
Hi enthuguy,

Sorry for not paying attention to this question earlier.
I will object to the deletion and explain what you are doing wrong.
I hope it is still relevant to you, I only saw this now.
If it is no longer relevant... ignore my response and continue deletion, no problem with that

Geert
Gertone (Geert Bormans)Information Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
Will still try to provide an answer
Information Architect
CERTIFIED EXPERT
Top Expert 2006
Commented:
Here is the problem

<xsl:template match="ns1:ListOfFields/ns1:Field">
...

You have two templates with the same match.
This is not allowed, and two can not be active at the same time
The last one will be picked and depending on the processor, you will get a warning or an error

the trick is to be more specific in the template itself
meaning that the best practice in XSLT is to have three templates in this case (and drop the choose construct)

first template
<xsl:template match="ns1:ListOfFields/ns1:Field[ns1:ListOfFieldTranslations/ns1:FieldTranslation[starts-with(ns1:DisplayName, 'First')]]"/>

Open in new window


second template
<xsl:template match="ns1:ListOfFields/ns1:Field[ns1:ListOfFieldTranslations/ns1:FieldTranslation[starts-with(ns1:DisplayName, 'Third')]]"/>

Open in new window


The empty template will delete these nodes

A third template should serve as a fallback for cases that don't apply to the condition
You don't need a specific template for these "otherwise", since these will be picked up by the generic identity copy you already have

<xsl:template match="@*|node()" >
          <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
          </xsl:copy>
      </xsl:template>

Open in new window


If no longer relevant, I hope you learn something from this

Alternatively you can have 1 template and two when clauses in a big choose...
but what I propose is commonly considered best practice

So, you should
-always avoid choose constructs in favour of multiple templates with a predicate in the match
- never have two templates matching the same node with equal preference and equal mode

cheers

Geert

Author

Commented:
Thanks Geert, for correcting me.

I realized that after few days (reading) and when ahead with choose (for now)

Thanks and regards
Gertone (Geert Bormans)Information Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
welcome

(note that there is a Topic Area specific for XSLT, I follow that one up more closely)