Re: cannot find the namespace declarations from an extension function
Adrian Herscu <[email protected]>
| Newsgroups | gmane.text.xml.xalan.java.user |
|---|---|
| Message-ID | <[email protected]> |
I think that I have found an workaround :)
Instead of applying the transformation on a StreamSource object I am
applying it on a DOMSource object and now the lookupNamespaceUri method
works as expected.
Adrian.
Adrian Herscu wrote:
> 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);
> }
> }
>
>