Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT to remove tags/attributes belonging to a namespace

Tags:

xslt

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?

like image 617
Indian Avatar asked Jun 10 '11 20:06

Indian


People also ask

What is the use of namespace in XSLT?

In XML a namespace is a collection of names used for elements and attributes. A URI (usually, a URL) is used to identify a particular collection of names.

What is exclude result prefixes in XSLT?

exclude-result-prefixes. Specifies any namespace used in this document that should not be sent to the output document. The list is whitespace separated. extension-element-prefixes. Specifies a space-separated list of any namespace prefixes for extension elements in this document.

Is xsl and XSLT the same?

XSL Transformation (XSLT)XSLT is designed to be used as part of XSL. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.


1 Answers

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ns1="http://s1">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match=
 "*[not(attribute::ns1:*)
  and
    not(descendant-or-self::ns1:*)
   ]
 |
  @*[not(namespace-uri()='http://s1')]
 "/>
</xsl:stylesheet>

when applied on the provided XML document:

<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>

produces the wanted, correct result:

<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>

Explanation:

  1. The identity rule (template) copies every node "as-is".

  2. 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.

like image 182
Dimitre Novatchev Avatar answered Sep 21 '22 00:09

Dimitre Novatchev