I have a problem of getting <style xml:space="preserve" type="text/css"
xml:space="preserve"> tags in exported SVG files. This has been addressed
before on the mailing list, named as a bug in pretty printer, and that
it has been fixed in CVS version.
So, I downloaded the CVS version, but the bug didn't go away. So I did
some further research with it, and it seems to be a loader bug. My loading
code looks like this:
SVGDocument doc = null;
try {
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
String uri = aFile.toURL().toString();
doc = (SVGDocument)factory.createSVGDocument(uri);
} catch (IOException ex) {
ex.printStackTrace();
}
but it really doesn't matter as the same thing happens if I get the document
from JSVGCanvas where it has been loaded with setURI().
To find out what happens I made a test right after loading:
protected static void printStyleElements(SVGDocument aDocument) {
// get the root elements (the svg element)
Element root = aDocument.getDocumentElement();
// Collect all "style" elements from the document
NodeList elements = root.getElementsByTagName("style");
for (int n = 0; n < elements.getLength(); n++) {
System.out.println("style "+n+":");
Element elem = (Element)elements.item(n);
// get the attributes of the element
NamedNodeMap attr = elem.getAttributes();
for (int p = 0; p < attr.getLength(); p++) {
Attr a = (Attr)attr.item(p);
System.out.println("attr "+a.getName()+" "+a.getValue());
}
}
}
For the mathMetal.svg sample file for example this gives the following info:
style 0:
attr xml:space preserve
attr type text/css
attr xml:space preserve
So, there really are two "xml:space=preserve" attributes in that style
element. How they got there is beyond me; in the original document there's
none.
So I decided to device a kludge around this by removing the double
attributes. No luck there: when I found the duplicate attribute and
removed it (with removeAttributeNode), it had no effect. Probably I
managed to remove the attribute, but it was immediately replaced,
as the documentation says:
"If the removed Attr has a default value it is immediately
replaced. The replacing attribute has the same namespace URI and
local name, as well as the original prefix, when applicable."
Probably removeAttributeNode doesn't detect that the attribute already
exists as a double (as that shouldn't be possible) and forces the
attribute back there.
So I had to device another kludge around this. This time I got it working,
but it's not a nice thing to have these in the code.. :) This is a longish
method, but if things are done in the wrong order, either the duplicate
has double "xml:space=preserve" attributes or the style doesn't work
anymore...
protected static void cleanupStyleElements(SVGDocument aDocument) {
// get the root elements (the svg element)
Element root = aDocument.getDocumentElement();
// Collect all "style" elements from the document
NodeList elements = root.getElementsByTagName("style");
for (int n = 0; n < elements.getLength(); n++) {
Element sourceElement = (Element)elements.item(n);
Element targetElement = aDocument.createElementNS(
sourceElement.getNamespaceURI(),
sourceElement.getLocalName());
// get the attributes of the element, use a Hashtable for
// detecting doubles and copy to targetElement.
// get existing attributes from targetElement to hashtable
NamedNodeMap attr = targetElement.getAttributes();
Hashtable ht = new Hashtable();
for (int p = 0; p < attr.getLength(); p++) {
Attr a = (Attr)attr.item(p);
ht.put(a.getName(),a.getValue());
}
// seek source attributes for attributes that don't exist yet,
// or whose value is different.
attr = sourceElement.getAttributes();
for (int p = 0; p < attr.getLength(); p++) {
Attr a = (Attr)attr.item(p);
String name = a.getName();
String value = a.getValue();
if (!ht.containsKey(name)) {
// if the attribute doesn't exist
ht.put(name,value);
targetElement.setAttributeNodeNS(a);
} else if (!value.equals((String)ht.get(name))) {
// If the attribute exists but with a different value
// (I'm not certain if this works... it could be
// that the result is duplicate attribute with different
// value.)
ht.put(name,value);
targetElement.setAttributeNodeNS(a);
}
}
// move child nodes of the sourceElement to targetElement
Node node = sourceElement.getFirstChild();
while (node != null) {
sourceElement.removeChild(node);
targetElement.appendChild(node);
node = sourceElement.getFirstChild();
}
// replace sourceElement with targetElement
sourceElement.getParentNode().replaceChild(targetElement,
sourceElement);
}
}
Hope this helps those struggling with the same problem, and in fixing
the bug...
Kiia Kallio
Software Engineer
Fathammer Ltd.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]