Geoff,
this seems to be an issue with the DOM object that you want to serialize,
not a problem with an XSL transformation (Xalan), nor a problem with the
serializer that is part of Xalan.

You are using Xerces as your DocumentBuilderFactory, so I suggest to take
this issue up on one of the Xerces mailing lists.

I'm not DOM expert, so I don't quite know what your recent code fragment is
trying to do with namespaces.

My instinct says that the root of your problem may be how namespace nodes
are represented.

Consider this example, an element named "A" with a namespace node of prefix
"p1" mapped to URI "http://uri1";. Element "A" has direct child element "B"
that has two namespace nodes, "p1" mapped to URI "http://uri1"; and "p2"
mapped to "http://uri2";. Also, "B" has an attribute with name "attrb" and
value "valueb".

Each element has its own associated namespace nodes. This more or less is
the DOM point of view. When you serialize (write out a a stream of
characters or bytes) the above concepts you get this:
    <A xmlns:p1='http://uri1'><B  xmlns:p1='http://uri1'
xmlns:p2='http://uri2' attrb='valueb' /></A>

It is a feature of serialized XML that if a parent element has a namespace
mapping, xmlns:prefix='uri', then all decendant elements get that mapping
"for free".  So any serializer worth its salt wouldn't write out what I did
but this:
    <A xmlns:p1='http://uri1'><B  xmlns:p2='http://uri2' attrb='valueb'
/></A>

These attributes, the ones starting with xmlns, are not real attributes of
A and B, but are the representation of the namespace nodes associated with
A and with B when you serialize. When an XML parser, like Xerces reads such
a stream in it will convert the xmlns:prefix="uri" attributes back into
namespace nodes.  I'm not sure if it also leaves them as attribute values
as well.

If you want to generate the above described elements with SAX events you
will need:
handler.startPrefixMapping("p1","http://uri1";);
handler.startElement(...) ; // for A
handler.startPrefixMapping("p1","http://uri1";);
handler.startElement(...) ; // for B, and the attributes object passed in
here contains attrb with value valueb
endElement() // end B
endElement() // end A

If you tried to do it like this, I don't think the meaing is the same:
handler.startElement(...) ; // for A, and the attributes object passed in
here contains xmlns:p1 with value http://uri1
handler.startElement(...) ; // for B, and the attributes object passed in
here contains attrb with value valueb and xmlns:p2 with value http://uri2
endElement() // end B
endElement() // end A

It may look the same when serialized, but neither A nor B had any namespace
nodes.

Element A has one attribute named xmlns:p1 with value http://uri1.  However
I don't think this is namespace node.  If you squeezed these SAX events
into a DOM, and asked the DOM for a list of namespace nodes associated with
A I don't think it would include a namespace node for p1. It isn't a
namespace node, it is just an attribute that happens to look like a
namespace node.  With SAX you want to use the namespaceMapping() calls to
declare namespace nodes.



- Brian
- - - - - - - - - - - - - - - - - - - -
Brian Minchau
XSLT Development, IBM Toronto
e-mail:        [EMAIL PROTECTED]

"You want it today? I thought tomorrow was yesterday, and I still had more
time." - My daughter.



                                                                           
             Geoffrey Shuetrim                                             
             <[EMAIL PROTECTED]                                             
             >                                                          To 
                                       xalan                               
             06/02/2005 10:27          <[email protected]>      
             PM                                                         cc 
                                                                           
                                                                   Subject 
             Please respond to         Re: Losing namespace declarations   
                   geoff               for namespaces that are used  only  
                                       on attributes (eg xlink) when using 
                                       org.apache.xml.serializer           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           




OK - I am stumped:

The original Document that I use to start the chain of XSLT
transformations is also losing its namespace declarations for attribute
only namespaces when it is serialised - IE - before any transformations
so I think I can rule out any side effects of the transformation
process.

I can also run the following code against the original Document:

NodeList n = document.getElementsByTagNameNS(
  "http://www.xbrl.org/2003/linkbase";,
  "linkbaseRef"
);
Element e = (Element) n.item(0);
String type = e.getAttributeNS("http://www.w3.org/1999/xlink","type";);
System.out.println(type);

and I get back the text: "simple", which is what I was after for an
XLink simple link.  This suggests to me that the XLink attribute does
have its namespace declaration in the Document that is serialized
incorrectly.

I also run:

System.out.println(document.getClass().getName());

and it produces "org.apache.xerces.dom.DocumentImpl", telling me (I
think) that I am working on the intended Document implementation.

Running Brian's code results in my not losing any namespaces for the
trivial example that I provided, either when creating the original XML
as a string or when loading it into a DOM Document from a file.
Similarly, I can parse in very large complex XML files that correspond
closely to what I am having trouble serializing, and then serialize them
again without losing the namespaces.

That leaves me with the view that the problem lies in there being some
difference between the DOM Document that I build up in memory from a
series of SAX events (my original DOM Document) and the kinds of DOM
Documents created when I parse XML from files or Strings.  When I add
attributes to the original DOM Document, I use the following:

for (int i = 0; i < attrs.getLength(); i++) {

  if (attrs.getURI(i) == XMLNamespace) // Handle the XML
    namespacenewElement.setAttribute(
      attrs.getQName(i),
      attrs.getValue(i)
    );
  else
    newElement.setAttributeNS(
      attrs.getURI(i),
      attrs.getQName(i),
      attrs.getValue(i)
    );
}

My understanding is that this code is setting up the namespace nodes for
the attributes correctly as well as adding the attributes themselves.
This seems to be borne out by the success of the stylesheets that I can
apply to this original DOM Document.

That leaves me with a big zero in terms of the number of possible
differences I can think of.  Suggestions are welcome.

Cheers

Geoff Shuetrim



On Thu, 2005-06-02 at 17:17 -0400, Brian Minchau wrote:
> Goeff,
> I tried two things. The first was to run your input XML through the
> identity transform, which will essentially use the same code underneath,
> but not use DOM at all.
> Here is the code I ran:
>     static void case3() throws TransformerException, IOException {
>         final javax.xml.transform.TransformerFactory tFactory;
>         tFactory = new
org.apache.xalan.processor.TransformerFactoryImpl();
>
>         final javax.xml.transform.Transformer transformer;
>         transformer = tFactory.newTransformer();
>
>         StringWriter sw = new StringWriter();
>         StringReader sr = new StringReader(
>             "<?xml version='1.0' ?>\n" +
>             "<c:a xmlns:b='http://somenamespace.com/'\n"+
>             "     xmlns:c='http://othernamespace.com/'\n"+
>             "     b:d='e'/>");
>         StreamResult  strmrslt = new StreamResult(sw);
>         StreamSource  strmsrc  = new StreamSource(sr);
>
>         transformer.setOutputProperty("method","xml");
>         transformer.setOutputProperty("indent","yes");
>         transformer.setOutputProperty("standalone","no");
>         transformer.transform(strmsrc, strmrslt);
>
>
>         sw.flush();
>         String out = sw.toString();
>         sw.close();
>         System.out.println("=================================");
>         System.out.println(out);
>         System.out.println("=================================");
>
>     }
>
> Here is the output that I got:
> =================================
> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
> <c:a xmlns:b="http://somenamespace.com/";
> xmlns:c="http://othernamespace.com/"; b:d="e"/>
>
> =================================
>
> Then I tried with Xerces as the creator of the DOM.
>
>     public static void case4()
>         throws SAXException, IOException, ParserConfigurationException {
>
>         javax.xml.parsers.DocumentBuilderFactory dfactory;
>         //  dfactory =
>         //    javax.xml.parsers.DocumentBuilderFactory.newInstance();
>
>         dfactory = new
org.apache.xerces.jaxp.DocumentBuilderFactoryImpl();
>         dfactory.setNamespaceAware(true);
>
>
>
>         final org.w3c.dom.Document document;
>         {
>             StringReader sr =
>                 new StringReader(
>                 "<c:a xmlns:b='http://somenamespace.com/' "+
>                 "     xmlns:c='http://othernamespace.com/' b:d='e'/>");
>             StreamSource strmsrc = new StreamSource(sr);
>             InputSource is = new InputSource(sr);
>
>
>             javax.xml.parsers.DocumentBuilder dBuilder =
>                 dfactory.newDocumentBuilder();
>             document = dBuilder.parse(is);
>         }
>
>         final StringWriter sw = new StringWriter();
>
>         {
>             java.util.Properties xmlProps =
>
OutputPropertiesFactory.getDefaultMethodProperties("xml");
>             xmlProps.setProperty("indent", "yes");
>             xmlProps.setProperty("standalone", "no");
>             Serializer serializer =
> SerializerFactory.getSerializer(xmlProps);
>             serializer.setWriter(sw);
>             serializer.asDOMSerializer().serialize(document);
>         }
>
>         sw.flush();
>         String out = sw.toString();
>         sw.close();
>         System.out.println("=================================");
>         System.out.println(out);
>         System.out.println("=================================");
>
>     }
>
> Whether the factory (dfactory) was set to be namespace aware, or not,
made
> no difference in what I got. The same output in all cases. Namespace
nodes
> were not lost.
>
> I don't know how you get your DOM document, but I think that is where the
> problem is.
>
> - Brian
> - - - - - - - - - - - - - - - - - - - -
> Brian Minchau
> XSLT Development, IBM Toronto
> e-mail:        [EMAIL PROTECTED]
>
> "If the lion purrs, it is only because it is saving you for dessert." -
My
> wife
>
>
>
>

>              Geoffrey Shuetrim

>              <[EMAIL PROTECTED]

>              >
To
>                                        xalan

>              06/02/2005 05:21          <[email protected]>

>              AM
cc
>

>
Subject
>              Please respond to         Losing namespace declarations for

>                    geoff               namespaces that are used only on

>                                        attributes (eg xlink) when using

>                                        org.apache.xml.serializer

>

>

>

>

>

>

>
>
>
>
> The subjects says most of it.  I am trying to serialize the results of
> stylesheet transformations and some xmlns declarations are going
> missing.
>
> For example, if I am serializing the following markup:
>
> <c:a
> xmlns:b="http://somenamespace.com/";
> xmlns:c="http://othernamespace.com/";
> b:d="e"/>
>
> then I get the following:
>
> <c:a
> xmlns:c="http://othernamespace.com/";
> b:d="e"/>
>
> The serialize method that I have written is:
>
> public void serialize(
>              OutputStream outputStream,
>              Document document)
> throws Exception {
>   java.util.Properties xmlProps =
>     OutputPropertiesFactory.getDefaultMethodProperties("xml");
>   xmlProps.setProperty("indent", "yes");
>   xmlProps.setProperty("standalone", "no");
>   Serializer serializer =
>     SerializerFactory.getSerializer(xmlProps);
>   serializer.setOutputStream(outputStream);
>   serializer.asDOMSerializer().serialize(document);
> }
>
> The document being serialized has always been parsed by a namespace
> aware DOM builder or created by a transformer applied to a namespace
> aware DOM and created from a stylesheet parsed in using a namespace
> aware DOM builder.
>
> The nearest archived message that I have come across is:
> http://mail-archives.apache.org/mod_mbox/xml-security-dev/200409.mbox/%
> [EMAIL PROTECTED]
> but that relates to XMLSerializer.
>
> Any guidance on what is going on would be very welcome!
>
> Geoff Shuetrim
>
>
>
>



Reply via email to