Use XSLT to reveal Page XMLNS - xslt

I am creating a quick-ref stylesheet for my XML files, and part of that reference is seeing which xml namespace I am using in each file.
For example, the start tage of gen_info.xml is:
<GeneralInfo xmlpre="Gen" xmlns="http://www.mrinitialman.com/">
Displaying the attribute "xmlpre" is easy enough: <xsl:value-of select="#xmlpre" /> . But <xsl:value-of select="#xmlns" /> seems to do nothing. What am I missing?

What am I missing?
You are missing the fact that xmlns="http://www.mrinitialman.com/" is not an attribute but a namespace declaration. It puts the GeneralInfo element and its descendants in a default namespace whose URI is "http://www.mrinitialman.com/".
You can use the namespace-uri() function to retrieve the namespace URI of a node. If - as it seems* - you are in the context of the GeneralInfo element, then:
<xsl:value-of select="namespace-uri()"/>
will return:
http://www.mrinitialman.com/
Note that an element can be in a namespace inherited from an ancestor element or determined by a prefix attached to its name; IOW, the namespace-uri() function returns the namespace URI of the argument node, not of a namespace declaration.
--
(*) It's not clear from your question how you get into the context of the GeneralInfo element, since it is in a namespace.

Related

Adding namespace in root gets copied to child nodes

In below example which I found on this site, an empty xmlns="" gets copied in all child nodes. What can the reason be for this mistake?
My Template:
<xsl:element xmlns="http://www.element-examples.org" name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
OUTPUT:
<projectgegevens xmlns="http://www.element-examples.org">
<idopdracht **xmlns=""**>28062262</idopdracht>
<projectcode **xmlns=""**>160622</projectcode>
<projectnaam **xmlns=""**>FF0000390001</projectnaam>
<ordernummer xmlns="">M2M-2022010071</ordernummer>
<projectleider xmlns="">FF000039003</projectleider>
<opmerking xmlns=""></opmerking>
<status xmlns="">5</status>
<datumverwacht xmlns="">2022-06-29</datumverwacht>
<certificaatnummer xmlns="">2020083810</certificaatnummer>
<analysemonsters xmlns="">
We can't tell you specifically what you did wrong without seeing all your code, but the namespace declaration xmlns="" is generated by the serializer when it finds that the result tree has an element in no namespace, whose parent is in a namespace (but with no prefix).
To find out why the child elements are in no namespace, rather than in the same namespace as their parent, you need to look at the XSLT code that creates the child elements. Note that the namespace of an element is determined entirely by the instruction that creates the element; it is never inherited automatically from the namespace of its parent element in the result tree (though it may be inherited from the parent element in the stylesheet).

How to retrieve specific namespace in XML files using Xpath

I do have an XML file that starts as following:
<wfs:WFS_Capabilities xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" ...>
I do have the full xml file in an xsl:variable named="CAPAPILITIES" and the namespace identifier "ogc" in an xsl:variable named "prefix". I tried the following but it does not work:
<xsl:value-of select="$CAPABILITIES/namespace::*[name()='$prefix']" />
and the namespace identifier "ogc" in an xsl:variable named "prefix"
You need to remove the quotes around $prefix:
<xsl:value-of select="$CAPABILITIES/namespace::*[name()=$prefix]" />
in order to compare the namespace node's name() against the value of the prefix variable instead of against the literal string "dollar-prefix".

XSLT: How get rid of default namespace's prefixes in XPath? (xmlns="...")

I have a template:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="urn:jboss:domain:1.1"
xmlns:d="urn:jboss:domain:1.1"
>
...
<xsl:template match="//d:interfaces/d:interface[#name='management']/d:inet-address">
...
</xsl:template>
This works.
<xsl:template match="//interfaces/interface[#name='management']/inet-address">
...
</xsl:template>
Why this doesn't work despite I have a default namespace set?
<xsl:template match="//interfaces/interface[#name='management']/inet-address">
...
</xsl:template>
Why this doesn't work despite I have a default namespace set?
This is one of the most FAQ on any XSLT and/or XPath list.
XPath treats any unprefixed name as belonging to "no namespace" -- regardless of the fact that there may be a default namespace defined and in scope.
To quote the W3C XPath 1.0 specification:
"A QName in the node test is expanded into an expanded-name using the
namespace declarations from the expression context. This is the same
way expansion is done for element type names in start and end-tags
except that the default namespace declared with xmlns is not used: if
the QName does not have a prefix, then the namespace URI is null"
Therefore the template rule above is matching elements that are in "no namespace", but the elements of the XML document are in the "urn:jboss:domain:1.1" namespace -- therefore not a single node is matched by the above rule.

Local XML namespace definition not working as I expected

I'm processing an XMI document exported from ArgoUML. It has elements of the form
<UML:DataType href='http://argouml.org/profiles/uml14/default-uml14.xmi#-84-17--56-5-43645a83:11466542d86:-8000:000000000000087C'/>
which points to an item of the form
<UML:DataType xmi.id="-84-17--56-5-43645a83:11466542d86:-8000:000000000000087C"
name="Integer"
isSpecification="false"
isRoot="false"
isLeaf="false"
isAbstract="false"/>
I've already declared xmlns:UML="org.omg.xmi.namespace.UML" at the top of the xslt file. I think I should be using something like :
<xsl:variable name="typeref" select="#href"/>
<xsl:variable name="ns" select='substring-before($typeref, "#")'/>
<xsl:variable name="identifier" select='substring-after($typeref, "#")'/>
<xsl:value-of xmlns:UML="$ns"
select='//UML:DataType[#xmi.id="$identifier"]/#name'/>
to deduce that my UML attributes type is Integer but this gives me
SystemId Unknown; Line #136; Column #94; A location step was expected following the '/' or '//' token.
If I change the xmlns to AAA then I get no error but an empty tag. I'm using Xalan2 on Debian squeeze. What am I missing?
Don't mind me. Just making the classic mistake of conflating namespaces and URIs. What I really needed was <xsl:value-of select='document($ns)//UML:DataType[#xmi.id=$identifier]/#name'/>

Fallback behavior when an XSLT extension function is not present

Is it possible to provide fallback behavior when a function implemented in an external XSLT object is not present (in XSLT 1.0)?
Right now, I have something similar to
<xsl:template match="an-element">
<xsl:value-of select="external-ns:ExternalFunction(.)" />
</xsl:template>
However, it's possible to generate content that makes sense if external-ns is not available, it just won't be as smart. So, I'd like to have something like
<!-- (pseudo) -->
<xsl:template match="an-element">
<xsl:try>
<xsl:value-of select="external-ns:ExternalFunction(.)" />
<xsl:catch>
<!-- do something else with the node -->
</xsl:catch>
</xsl:try>
</xsl:template>
I'm aware of xsl:fallback and element-available() but these seem to be only for elements, not functions. Is there any way to achieve this?
From http://www.w3.org/TR/xslt#function-function-available
Function: boolean function-available(string)
The argument must evaluate to a string
that is a QName. The QName is expanded
into an expanded-name using the
namespace declarations in scope for
the expression. The function-available
function returns true if and only if
the expanded-name is the name of a
function in the function library. If
the expanded-name has a non-null
namespace URI, then it refers to an
extension function; otherwise, it
refers to a function defined by XPath
or XSLT.