[xsl] Re:Re: [xsl] XSLT/XPATH 2.0 - except example.

Subject: [xsl] Re:Re: [xsl] XSLT/XPATH 2.0 - except example.
From: "Knight, Michel" <michel.knight@xxxxxxxx>
Date: Thu, 23 Jul 2009 16:12:44 -0400
Hi Wendell,
Thx for the guidance I was able to read and learn about "modified
identity transform".
I was able to have it working with a few modification I've included the
code.

The only thing that I don't want in the result is the tag "center".
Ex:
In the result I'm getting this
<div xmlns="http://www.w3.org/1999/xhtml"; class="center">   get ride of
this
<div>                                                       also get
ride of this
Is it easy not to remove the "div" tag and is attribute with this
approach?
Or should I be looking at another approach, I do like this one :-)


Here my XSL file:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xhtml="http://www.w3.org/1999/xhtml";>
  <xsl:output method="xml" indent="yes" encoding="windows-1252"
exclude-result-prefixes="xhtml" ></xsl:output>
  <xsl:strip-space elements="*"/>

  <xsl:template match="xhtml:html" exclude-result-prefixes="xhtml" >
   <root>
    <content>
	<xsl:apply-templates select="//xhtml:div[@class='center']" />

    </content>
   </root>
  </xsl:template>

  <xsl:template match="//xhtml:div[@class='center']">
    <xsl:copy>
      <xsl:copy-of select="@*"  copy-namespaces="no" />
      <xsl:apply-templates mode="remove"/>
    </xsl:copy>
  </xsl:template>

  <!--only remove does -->
  <xsl:template match="xhtml:h1"  mode="remove"/>
  <xsl:template match="xhtml:h2"  mode="remove"/>

  <!-- Don't execute this, just for testing -->
  <xsl:template match="//xhtml:div[@class='border']">
      Extra extra border information- shouldn't be process- just for
testing
  </xsl:template>
</xsl:stylesheet>

My HTML file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
<html xmlns="http://www.w3.org/1999/xhtml"; lang="en" xml:lang="en">
<head>
</head>
<body>
<!--googleoff:all-->
<div class="page">
Some info in the div page
<div class="center">
Some info in the div center
<div class="border">
Some info in the div border
<h1>
<a name="cont" id="cont">
 Aviation Security </a>
 </h1>
<p>The Government of Canada has committed more than $2.6&nbsp;billion to
enhancing aviation security since 2001, and air travel has become much
safer as a result. Transport Canada is working diligently to make
further improvements for a secure Canadian aviation system - one that is
protected against unlawful interference, terrorist attacks or use as a
means to attack our allies. The department's aviation security programs
include the following:</p>
<h2>this is h2</h2>

</div>
</div>
</div>
</body>
</html>



------------------------------------------------------------------------
--
Hi Michel,

What you are missing is an understanding of XPath syntax and how it is
relating to your tree architecture.

It becomes clearer if you expand your XPaths into long syntax. You are
currently using abbreviated syntax.

So --

First the XPath that is working for you:

* except(//xhtml:div[@class='border'])

is short for

child::* except
(/descendant-or-self::node()/child::xhtml:div[attribute::class='border']
)

This is saying: "copy all children, excluding from this set any members
of the set of xhtml:div[@class='border'] elements anywhere in the
document".

Now the XPath that isn't working:

* except (//xhtml:div[@class='border']//xhtml:h1)

This is short for

child::* except
(/descendant-or-self::node()/child::xhtml:div[attribute::class='border']
/descendant-or-self::node()/child::xhtml:h1)

This is saying: "copy all children, excluding from this set any members
of the set of xhtml:h1 descendants of xhtml:div[@class='border']
elements anywhere in the document"

Your stylesheet is doing this. Since no xhtml:h1 elements are children
of the context node where the expression is evaluated (whichever
xhtml:div[@class='center'] has matched your template), all the children
are copied. (There are some among the descendants of the children you
have asked to copy, but the 'except' operation doesn't work that way.)

In order to accomplish your filtering, you can't simply use a copy-of
instruction, since xsl:copy-of simply copies subtrees from your source
document without change. That is, you can exclude branches from being
copied by using XPath as in your first case, but having decided to copy
a branch using xsl:copy-of, you can't also modify it.

In order to do this, you need to use a somewhat more sophisticated
approach. Your problem is actually a good example of what we call a
"modified identity transform", since the result is just a modified
version of the source. It could be done in a stylesheet with two
templates like this:

<xsl:template match="*">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

<xsl:template match="xhtml:h1"/>

How does this work? You need to read up on templates and the
xsl:apply-template instruction.

The idea of the "context node" and its relation to the evaluation of
XPath is also critical.

Good luck --
Wendell

At 04:44 PM 7/22/2009, you wrote:
	Using Saxon 9
	Windows
	XSLT/XPATH 2.0

	Hi,

	I'm trying to remove the h1 from my source with the "except" and
it
	doesn't work.
	ex:<xsl:copy-of  select="* except
	(//xhtml:div[@class='border']//xhtml:h1)" />
	When I do the same logic to class=border section it work??
	<xsl:copy-of  select="* except(//xhtml:div[@class='border'])" />
	What I'm I missing, with the except for the removal of that
section
	h1???
	Note: source code included.
	Regards,

	Michel

	---------------   My StyleSheet
	<xsl:strip-space elements="*"/>
	<xsl:template match="xhtml:html" exclude-result-prefixes="xhtml"
>
	<root>
	                        <content>
	                                <xsl:apply-templates
	select="//xhtml:div[@class='center']"
exclude-result-prefixes="xhtml"/>
	                        </content>
	</root>
	</xsl:template>
	<!--

=======================================================================
	-->
	<!--*****************************************-->
	<!-- Content section just remove the right nav-->
	  <xsl:template match ="//xhtml:div[@class='center']"
	exclude-result-prefixes="xhtml">
	                <!-- Right Nav first-->
	                Remove h1
	            <!-- THIS doesn't WORK, why????? -->
	                        <xsl:copy-of  select="* except
	(//xhtml:div[@class='border']//xhtml:h1)" />
	            END of remove h1
	            <!-- THIS WORK -->
	               <xsl:copy-of  select="*
	except(//xhtml:div[@class='border'])" />
	  </xsl:template>
	<!--*****************************************-->
	</xsl:stylesheet>
	---------------   My Source
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "">
	<html xmlns="http://www.w3.org/1999/xhtml";; lang="en"
xml:lang="en">
	<head>
	</head>
	<body>
	<!--googleoff:all-->
	<div class="page">
	<div class="center">
	<div class="border">
	<h1>
	<a name="cont" id="cont">
	 Aviation Security </a>
	 </h1>
	<p>The Government of Canada has committed more than programs
include the
	following:</p>
	</div>
	</div>
	</div>
	</body>
	</html>

Current Thread