I’m trying to use XSLT to remove tags/attributes belonging to a namespace. The difficulty is that tags from differnt namespaces can be embedded in each other.
Sample:
<?xml version="1.0" encoding="utf-8"?>
<Collection xmlns="http://s0" xmlns:ns1="http://s1">
<Identifier Name="CollectionX"
ns1:GlobalID="{E436833B-B0A6-4E0D-804B-60052B767AE3}"
ns1:LocalID="{0130C866-7A91-4544-A82B-E0C0F2E3BCB2}" />
<Properties>
<ns1:Collectible>1982</ns1:Collectible>
<Displayed>Reserved</Displayed>
<Picture>Reserved.jpeg</Picture>
</Properties>
<WeakLinks>
<Link Type="resource" Language="en-us"/>
</WeakLinks>
</Collection>
I want to filter all tags/properties that do not belong to ns1 as long as they do not have any ns1 children.
So the result should be:
<?xml version="1.0" encoding="utf-8"?>
<Collection xmlns="http://s0" xmlns:ns1="http://s1">
<Identifier
ns1:GlobalID="{E436833B-B0A6-4E0D-804B-60052B767AE3}"
ns1:LocalID="{0130C866-7A91-4544-A82B-E0C0F2E3BCB2}" />
<Properties>
<ns1:Collectible>1982</ns1:Collectible>
</Properties>
</Collection>
How can I accoplish this with XSLT? Any help?
This transformation:
when applied on the provided XML document:
produces the wanted, correct result:
Explanation:
The identity rule (template) copies every node “as-is“.
There is just one template overriding the identity rule. This templates has no body — meaning that it effectively filters (deletes) any matched node from being copied to the output. The nodes matched are exactly the ones that must be filtered out: 1) any element that doesn’t have attributes belonging to the namespace to which the prefix
ns1:is bound and also isn’t itself belonging to that namespace and also it has no descendent element nodes belonging to that namespace. And 2) any attribute that doesn’t belong to that namespace.Remember: Overriding the identity rule is the most fundamental and most powerful XSLT design pattern. More about this design pattern can be found here.