Remove namespace declaration from XSLT stylesheet using XSLT

I have an XSLT stylesheet, for example:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension" xmlns:saxon="http://saxon.sf.net/"> <saxon:script language="java" implements-prefix="XQHeaderFunc" src="java:com.sonicsw.xq.service.xform.HeaderExtension" /> <xsl:output indent="yes" omit-xml-declaration="yes"/> <xsl:template match="/"> <xsl:variable name="processId" select="XQHeaderFunc:getProperty(XQHeaderFunc:new(),'processId',-1)" /> <xsl:value-of select="XQHeaderFunc:setProperty(XQHeaderFunc:new(),'processId',string(@id),-1)"/> <root> <xsl:apply-templates /> </root> </xsl:template> <!-- Other stuff --> </xsl:stylesheet> 

I want to convert this stylesheet using the second XSLT stylesheet to remove everything related to the XQHeaderFunc and saxon spaces. Is there a way I can do this?


Now I tried the following, which works successfully with elements, but the namespace declaration does not seem to want to fade.

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension" xmlns:saxon="http://saxon.sf.net/" exclude-result-prefixes="XQHeaderFunc saxon"> <xsl:param name="XQHeaderReplacement" /> <xsl:variable name="apos">'</xsl:variable> <!-- Copy all nodes --> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <!-- Remove saxon script tag --> <xsl:template match="saxon:script" /> <!-- Remove elements with setProperty calls --> <xsl:template match="*[starts-with(@select, 'XQHeaderFunc:setProperty')]" /> <!-- Replace getProperty calls with replacement value--> <xsl:template match="@select[starts-with(., 'XQHeaderFunc:getProperty')]"> <xsl:attribute name="select"> <xsl:value-of select="concat($apos, $XQHeaderReplacement, $apos)"/> </xsl:attribute> </xsl:template> </xsl:stylesheet> 

Output:

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:XQHeaderFunc="java:com.sonicsw.xq.service.xform.HeaderExtension" xmlns:saxon="http://saxon.sf.net/"> <xsl:output indent="yes" omit-xml-declaration="yes" /> <xsl:template match="/"> <xsl:variable name="processId" select="''" /> <root> <xsl:apply-templates /> </root> </xsl:template> <!-- Other stuff --> </xsl:stylesheet> 
+4
source share
1 answer

I would add

  exclude-result-prefixes="foo" 

to your

  <xsl:stylesheet> 

element. Then the namespace declaration for foo will be omitted if possible, i.e. If there are no elements or attributes in this namespace.

FYI, the reason for this line

 <xsl:template match="xsl:stylesheet/@xmlns:foo" />` 

throws an error because xmlns:foo in the input document is not an attribute; This is a pseudo attribute. What your matching pattern requests matches an attribute named foo , which is in the namespace matching the xmlns namespace prefix. Since you did not declare the xmlns namespace prefix in your stylesheet, you get the error "xmlns prefix is ​​not defined".

Update:

I see from your published output (and my own testing) that exclude-result-prefixes failed to remove the namespace declaration.

1) First, I would ask why this matters. It does not change the namespace of anything in your output XSLT. Are you just trying to remove it for aesthetic reasons?

2) If you look at the XSLT 1.0 spec, it seems to me that <xsl:copy> does not pay attention to exclude-result-prefixes :

Creating an instance of the xsl: copy element creates a copy of the current node. The namespace nodes of the current node are automatically copied as well ...

AFAICT, only literal result elements will skip namespace nodes based on exclude-result-prefixes .

In this case, I would try to replace <xsl:copy> in your identity template (for elements) with <xsl:element name="{name()}"> or a variant thereof. Then you need a separate identification template for non-element nodes.

I replaced your identity template with the following two templates:

 <!-- Copy elements --> <xsl:template match="*" priority="-1"> <xsl:element name="{name()}"> <xsl:apply-templates select="node()|@*"/> </xsl:element> </xsl:template> <!-- Copy all other nodes --> <xsl:template match="node()|@*" priority="-2"> <xsl:copy /> </xsl:template> 

and this gave what, in my opinion, is the desired result, without extraneous ns declarations:

 <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:output indent="yes" omit-xml-declaration="yes" /> <xsl:template match="/"> <xsl:variable name="processId" select="''" /> <root> <xsl:apply-templates /> </root> </xsl:template> <!-- Other stuff --> </xsl:stylesheet> 

(I drew a space for clarity.)

+10
source

Source: https://habr.com/ru/post/1434677/


All Articles