2017-05-17 52 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解析器一个转换器?