How copy-of can only copy selected node in XSLT

Hi,
Question for Copy
input:
<Rel><IRel UID1="3a4d1d2909d0" UID2="35fe61082294" DefUID="AssetSupplier" />
<IObject UID="3a4d1d2909d0.AssetSupplier.35fe61082294" />
   <SPXSupplier>
   <ISPFOrganization  /><ISPFAdminItem /><IObject UID="b73ebb87-cd36-4c25-b9ed-35fe61082294"   Description="local supplier made in form (10C)" Name="CASTROL1200" /><ISupplierOrganization />
   </SPXSupplier>
</Rel>

Output:
I only want to skip SPXSupplier and its child node in my output
<Rel><IRel UID1="3a4d1d2909d0" UID2="35fe61082294" DefUID="AssetSupplier" />
<IObject UID="3a4d1d2909d0.AssetSupplier.35fe61082294" />
</Rel>

currently I am using this copy which copy all the things including the child,
<xsl:copy-of select="self::node()"/>
I only want <Rel>, <IRel> and <IObject> tags. excluding other stuff.
SANbuddiesAsked:
Who is Participating?
 
Geert BormansConnect With a Mentor Information ArchitectCommented:
The best way to simulate a copy-of is by having an identity copy
(example 1)
The identity copy does exactly what a deep copy such as xslcopy-of does

by specialising you can remove some nodes

if you want to remove SPX Supplier, you just add a template for doing so (example2)

This approach (removeing what needs to be removed) is easier to embed and extend then explicitely copying what needs to be added
example 1
----------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">
    <xsl:template match="node()">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

example 2
---------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">
    <xsl:template match="node()">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="SPXSupplier"/>
</xsl:stylesheet>

Open in new window

0
 
zc2Commented:
As soon as I know, the copy-of always copies all the subnodes.
To selective copy only desired elements try to implement something like in the sample below:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="iso-8859-1"/>
	<xsl:template match="/">
		<xsl:apply-templates select="*"/>
	</xsl:template>

	<xsl:template match="Rel|IRel|IObject|@*">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:apply-templates select="IRel|IObject|@*"/>
		</xsl:copy>
	</xsl:template>

</xsl:stylesheet>

Open in new window

0
 
SANbuddiesAuthor Commented:
sorry guys I am away from my computer wont be able to check your solution until I get back !
Appreciate your suggestions.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
SANbuddiesAuthor Commented:
Gertno:
hi,
   thanks for the answer, can you tell me if I am going to use the same approach i can skip all nodes by just creating template for each.
Does the level of the nodes matter?
<abc>
  <level1>
      <level2>
      <level2/>
  <level1/>
<abc/>
0
 
Geert BormansInformation ArchitectCommented:
"Does the level of nodes matter?"

No, that is exactly the difference between my approach and zc2's approach,
This method of reconstructing the deep tree (whilst removing some parts)
works regardless of the depth

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

This template assures that every node that does not have its own template gets copied AND that its children are processed

You can safely add an empty template for each node you want to remove
So that answers "i can skip all nodes by just creating template for each"

If you need to just remove the tags, but keep some of the children, you can add a template like this
    <xsl:template match="abc">
            <xsl:apply-templates select="node()"/>
    </xsl:template>
0
 
SANbuddiesAuthor Commented:
how about Node() how does it work or what node() really means in xslt?
and similar with apply-templates='node()' this is some sort of nesting ?

and if I want to skip some attributes is it possible? I know that its not same as nodes  and attributes are treated in different way.
0
 
Geert BormansInformation ArchitectCommented:
node() means any children
this includes child elements, text nodes, process instructions and comments
it excludes attributes

attributes are all copied with the <xsl:copy-of select="@*"/>

if you want to exclude an attribute 'foo' you can do this

<xsl:copy-of select="@*[not(local-name() = 'foo')]"/>

if you leave the line out completely, no attributes will be copied

if you only want to copy the attribute 'foo' you can do this
<xsl:copy-of select="@foo"/>
0
 
SANbuddiesAuthor Commented:
and if have to process the value of foo which will later dicide whether that node has to be copied or not?
0
 
Geert BormansInformation ArchitectCommented:
You can always add tests in predicates, but I think it would be wise if you would add an example here

<xsl:template match="abc[@foo = 'bar']"/>

will remove all <abc> on the condition that the value of attribute "foo" equals "bar"

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.