2017-05-17 5 views
0

Da SVG eine reguläre XML-Datei ist und die ImageTranscoder.transcode() API org.w3c.dom.Document akzeptiert, akzeptiert der jeweilige TranscoderInput-Konstruktor org.w3c.dom.Document; würde man, dass das Laden und Parsen erwarten Datei mit einem Java-Lager XML-Parser funktionieren würde:Verwendung von Vanilla W3C Dokument und Apache Batik SVG Rasterizer

TranscoderInput input = new TranscoderInput(loadSvgDocument(new FileInputStream(svgFile))); 
BufferedImageTranscoder t = new BufferedImageTranscoder(); 
t.transcode(input, null); 

Wo loadSvgDocument() Methode definiert ist als:

Document loadSvgDocument(String svgFileName, InputStream is) { 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    // using stock Java 8 XML parser 
    Document document; 
    try { 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     document = db.parse(is); 
    } catch (...) {...} 
    return document; 
} 

Es funktioniert nicht. Ich bekomme seltsame Casting-Ausnahmen.

Exception in thread "main" java.lang.ClassCastException: org.apache.batik.dom.GenericElement cannot be cast to org.w3c.dom.svg.SVGSVGElement 
at org.apache.batik.anim.dom.SVGOMDocument.getRootElement(SVGOMDocument.java:235) 
at org.apache.batik.transcoder.SVGAbstractTranscoder.transcode(SVGAbstractTranscoder.java:193) 
at org.apache.batik.transcoder.image.ImageTranscoder.transcode(ImageTranscoder.java:92) 
at org.apache.batik.transcoder.XMLAbstractTranscoder.transcode(XMLAbstractTranscoder.java:142) 
at org.apache.batik.transcoder.SVGAbstractTranscoder.transcode(SVGAbstractTranscoder.java:156) 

Hinweis: Klasse BufferedImageTranscoder ist meine Klasse, erstellt nach Batik Entwürfe, erstreckt ImageTranscoder die wiederum SVGAbstractTranscoder in dem Stack-Trace oben erwähnt erstreckt.

Leider kann ich nicht Batik eigene Parser verwenden, SAXSVGDocumentFactory:

String parser = XMLResourceDescriptor.getXMLParserClassName(); 
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser); 
svgDocument = (SVGDocument) f.createDocument(..); 

ich Papirus SVG icons zu machen versuchen, aber sie alle haben <svg ... version="1"> und SAXSVGDocumentFactory nicht so, und nicht auf die createDocument(..) mit Unsupport SVG version '1'. Sie haben wahrscheinlich nicht unterstützt gemeint.

Exception in thread "main" java.lang.RuntimeException: Unsupport SVG version '1' 
at org.apache.batik.anim.dom.SAXSVGDocumentFactory.getDOMImplementation(SAXSVGDocumentFactory.java:327) 
at org.apache.batik.dom.util.SAXDocumentFactory.startElement(SAXDocumentFactory.java:640) 
. . . 
at org.apache.batik.anim.dom.SAXSVGDocumentFactory.createDocument(SAXSVGDocumentFactory.java:225) 

Ändern version="1"-version="1.0" in der Datei selbst behebt das Problem und das Symbol gemacht wird für mich schön. Aber es gibt Hunderte (tausende) von Icons und das Reparieren von ihnen ist mühsam und ich würde effektiv einen Port ihres Projekts erstellen. Das ist kein Weg für mich. Viel einfacher ist es, die fix in der Laufzeit zu machen, mit DOM API:

Element svgDocumentNode = svgDocument.getDocumentElement(); 
String svgVersion = svgDocumentNode.getAttribute("version"); 
if (svgVersion.equals("1")) { 
    svgDocumentNode.setAttribute("version", "1.0"); 
} 

Aber das kann nur mit Lager Java XML-Parser, Batik XML-Parser bläst zu früh durchgeführt werden, bevor dieser Code erreicht werden kann, bevor Dokument wird generiert. Aber wenn ich Aktien-XML-Parser verwende, mache die Version zu reparieren, dann Batik Transcoder (Rasterizer) mag es nicht. Also habe ich hier eine Wand getroffen.

Gibt es einen Konverter von einem Lager XML-Parser produziert org.w3c.dom.Document und Batik kompatibel org.w3c.dom.svg.SVGDocument?

Antwort

0

OK, ich habe eine Lösung gefunden, die das Problem umgeht. Zum Glück Klasse SAXSVGDocumentFactory kann leicht Unterklassen und kritische Methode getDOMImplementation() überschrieben werden.

protected Document loadSvgDocument(InputStream is) { 
    String parser = XMLResourceDescriptor.getXMLParserClassName(); 
    SAXSVGDocumentFactory f = new LenientSaxSvgDocumentFactory(parser); 
    SVGDocument svgDocument; 
    try { 
     svgDocument = (SVGDocument) f.createDocument("aaa", is); 
    } catch (...) { 
     ... 
    } 
    return svgDocument; 
} 

static class LenientSaxSvgDocumentFactory extends SAXSVGDocumentFactory { 
    public LenientSaxSvgDocumentFactory(String parser) { 
     super(parser); 
    } 

    @Override 
    public DOMImplementation getDOMImplementation(String ver) { 
     // code is mostly rip-off from original Apache Batik 1.9 code 
     // only the condition was extended to accept also "1" string 
     if (ver == null || ver.length() == 0 
       || ver.equals("1.0") || ver.equals("1.1") || ver.equals("1")) { 
      return SVGDOMImplementation.getDOMImplementation(); 
     } else if (ver.equals("1.2")) { 
      return SVG12DOMImplementation.getDOMImplementation(); 
     } 
     throw new RuntimeException("Unsupported SVG version '" + ver + "'"); 
    } 
} 

Dieses Mal habe ich das Glück habe, bleibt die wichtigste Frage aber: Gibt es einen Konverter von einem Lager XML-Parser org.w3c.dom.Document und Batik org.w3c.dom.svg.SVGDocument kompatibel produziert?

Verwandte Themen