2017-05-17 51 views
0

由於SVG是一個常規XML文件,ImageTranscoder.transcode()API接受org.w3c.dom.Document,因此相應的TranscoderInput構造函數接受org.w3c.dom.Document;人們所期望的與Java股票XML解析器,加載和解析文件將工作:使用vanilla W3C文檔和Apache Batik SVG光柵器

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

loadSvgDocument()方法定義爲:

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; 
} 

它不工作。我得到奇怪的轉換異常。

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) 

注:BufferedImageTranscoder類是我的類,如每蠟染藍圖創建的,延伸ImageTranscoder這又延伸上述棧跟蹤提到SVGAbstractTranscoder

不幸的是我不能用蠟染自己的解析器,SAXSVGDocumentFactory

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

我試圖渲染Papirus SVG icons但他們都有<svg ... version="1">和SAXSVGDocumentFactory不喜歡這一點,失敗的createDocument(..)Unsupport SVG version '1'。他們可能意味着不受支持

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) 

文件本身的更改version="1"version="1.0"修復該問題,圖標是很好的渲染了我。但有數百(千)個圖標並修復它們都很乏味,我會有效地創建他們的項目的一個端口。這對我來說不是一個前進的方向。更容易是使運行時間修復,使用DOM API:

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

但只能用股票的Java XML解析器來完成,蠟染XML解析器吹太早,這個代碼可以達到之前,文檔前生成。但是,當我使用股票XML解析器,進行版本修復,然後Batik Transcoder(光柵化器)不喜歡它。所以我在這裏打了一堵牆。

是否有從股票XML分析器生產的轉換器org.w3c.dom.Document和兼容蠟染org.w3c.dom.svg.SVGDocument

回答

0

好的,我找到了一種繞過問題的解決方案。幸運的是,類SAXSVGDocumentFactory可以很容易地被子類和關鍵方法 getDOMImplementation()重寫。

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 + "'"); 
    } 
} 

這一次,我真的很幸運,主要的問題仍然不過:有沒有從生產org.w3c.dom.Document和蠟染兼容org.w3c.dom.svg.SVGDocument股票的XML解析器一個轉換器?