Hi Michael and thanks for the response.
Please see my comments between your lines.
Regards,
Adrian.
Michael Ludwig wrote:
<gen:test func="lookupNamespaceUri">
Now what's wrong with <xsl:value-of select="namespace-uri()"/> ?
No need to call an extension function here.
To get the URIs for all the namespace nodes in scope, try:
<xsl:for-each select="namespace::node()">
<NS><xsl:value-of select="."/></NS>
</xsl:for-each>
Please remember that this is just a simplified test case. My actual
problem is traversing relational data structures with less XSL code.
From the initial post:
<!-- key for looking up the wsdl:binding -->
<variable name="binding-key">
<apply-templates select="." mode="binding-key" />
</variable>
<for-each select="key('binding',$binding-key)">
...
</for-each>
(this also requires some infrastructure code -- the definitions for the
keys and the templates; and these definitions are required for each
relational structure in the input model, so it is very easy to mess
things around resulting in hours of debugging)
Instead of that I was looking for an extension function that will enable
me to write something like that:
<for-each select="myxslutils:ref(/wsdl:definitions/wsdl:binding,
'name', @binding, /wsdl:definitions/@targetNamespace)">
...
</for-each>
<!-- PROBLEM: works for 'wsdl' prefix,
for 'tns' and everything else,
e.g. 'soap', 'xsd', etc., returns null
-->
<value-of select="myext:lookupNamespaceUri(current(), 'tns')" />
Note you don't need current() here, although there is no harm in doing
so. The current() function is used to get the context node *outside* an
XPath expression from inside that expression when moving away from the
context node, which you're not doing. So you can just use ".", the dot,
which is the context node (or context item in XSLT 2.0).
public static String lookupNamespaceUri(final Node currentNode,
final String prefix) {
final String namespaceUri;
namespaceUri =
currentNode.getOwnerDocument().getDocumentElement()
.lookupNamespaceURI(prefix);
return namespaceUri;
}
I don't know why this doesn't return the expected result. A call to
getNodeName() works just fine.
But then, maybe the expectation is wrong. An XSLT 1.0 processor isn't
obliged to respect your choice of prefixes for namespaces,
Hmmm... It appears that the parser completely ignores all 'xmlns'
attributes. The interesting thing is that it reads attributes from other
non-null namespaces.
Try to add a breakpoint on
http://svn.apache.org/viewvc/xalan/java/trunk/src/org/apache/xml/dtm/ref/DTMNodeProxy.java?view=markup
line #1643
public String lookupNamespaceURI(String specifiedPrefix) {
...
if (this.hasAttributes()) {
NamedNodeMap map = this.getAttributes();
int length = map.getLength();
for (int i=0;i<length;i++) {
...
map.getLength returns 1 as if the 'targetNamespace' was the only
attribute. Tried to add
xmlns:foo="123"
foo:dummy="abc"
to the wsdl:definitions and now the map.getLength returns 2 and the
foo:dummy attribute node node is recognized correctly.
I tested this behavior with the Xerces parser, here is the test class:
package com.acme.apps;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import junit.framework.TestCase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
public class XmlOperationsTest
extends TestCase {
private static final String TEST_ROOT_DIR = "target/test-classes";
private static final String TEST_XML =
"com/acme/apps/convert-temperature-service.wsdl";
private static final File TEST_XML_FILE =
new File(TEST_ROOT_DIR, TEST_XML);
public final void testLookupNamespaceUri()
throws ParserConfigurationException, SAXException,
IOException {
final DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
final DocumentBuilder db = dbf.newDocumentBuilder();
final Document xml = db.parse(TEST_XML_FILE);
final Element documentElement = xml.getDocumentElement();
/* NOTE: stepping inside the implementation of the method below
reveals that the 'xmlns:' prefixed attributes are counted as the
rest of attributes, which is different than the Xalan's parser
behavior. Therefore, I think this is a bug in Xalan. */
final String tnsUri = documentElement.lookupNamespaceURI("tns");
System.out.println(tnsUri);
assertEquals("http://www.webserviceX.NET/", tnsUri);
}
}