简体   繁体   English

使用Batik读取SVG文件时使用自定义元素工厂

[英]Using Custom Element Factory When Reading SVG File Using Batik

I am trying to read a largish (1 MB) svg file that is exported from an old program. 我试图读取从旧程序导出的较大(1 MB)svg文件。 I do not have access to this program or the data. 我无权访问此程序或数据。 I only have this exported svg file and I will probably have to import a freshly exported svg file somewhat regularly from this source. 我只有这个导出的svg文件,我可能要从这个源中定期导入一个新导出的svg文件。 The first problem I find using batik is that it is very strict when reading this file. 我发现使用蜡染的第一个问题是它在读取此文件时非常严格。 Firefox has no problem reading and displaying this file for example. 例如,Firefox在读取和显示此文件时没有问题。 Batik (including Squiggle can not display it because of some "custom" tags within the document). Batik(包括Squiggle因文档中的某些“自定义”标签而无法显示)。 The exception I get is ... 我得到的例外是......

org.w3c.dom.DOMException: The current document is unable to create an element of the requested type (namespace: http://www.w3.org/2000/svg, name: menu).
    at org.apache.batik.dom.AbstractNode.createDOMException(AbstractNode.java:408)
    at org.apache.batik.dom.svg.SVGDOMImplementation.createElementNS(SVGDOMImplementation.java:211)
    at org.apache.batik.dom.svg.SVGOMDocument.createElementNS(SVGOMDocument.java:372)
    at org.apache.batik.dom.util.SAXDocumentFactory.startElement(SAXDocumentFactory.java:625)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2756)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
    at org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:431)
    at org.apache.batik.dom.util.SAXDocumentFactory.createDocument(SAXDocumentFactory.java:349)
    at org.apache.batik.dom.svg.SAXSVGDocumentFactory.createDocument(SAXSVGDocumentFactory.java:200)
    at com.samsix.nrg.io.SvgFileImporter.importFile(SvgFileImporter.java:74)

... So using the not entirely helpful link Writing a batik Dom Extension I managed to write the following ... ...所以使用不完全有用的链接写一个蜡染Dom扩展我设法写下面的...

    public ImportReport importFile( final String    uri )
    throws
        IOException
{
    String parser = XMLResourceDescriptor.getXMLParserClassName();
    SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);

    SVGDOMImplementation    implementation = (SVGDOMImplementation) factory.getDOMImplementation( null );

    implementation.registerCustomElementFactory( "http://www.w3.org/2000/svg",
                                                 "menu",
                                                 new ExtensibleDOMImplementation.ElementFactory() {
                                                    @Override
                                                    public Element create( final String prefix,
                                                                           final Document doc )
                                                    {
                                                        System.out.println( "Element.create: " + prefix );
                                                        return new GenericElement( "prefix",
                                                                                   (org.apache.batik.dom.AbstractDocument) doc );
                                                    }
                                                } );

    SVGDocument    doc = (SVGDocument) factory.createDocument( uri );

    System.out.println( doc.getDocumentURI() );
}

But I get the same error, the System.out.println() statement is never hit so it is apparently not registering my factory correctly. 但我得到相同的错误,System.out.println()声明永远不会被命中,所以它显然没有正确注册我的工厂。 On a side note is there anyway to make Batik less strict so that it just skips things it doesn't understand like Firefox does? 另外一点就是要让Batik不那么严格,以便它只是像Firefox一样跳过它不理解的东西?

Investigation indicates that the Batik 1.7.0 implementation doesn't allow you to create DOM extensions that intercept elements in the SVG namespace; 调查表明, Batik 1.7.0实现不允许您创建拦截SVG名称空间中元素的DOM扩展; it throws the exception at the point when it would otherwise drop through to the code that would do the lookup of the registered factory. 它会抛出异常,否则会导致查找已注册工厂的代码。 I've no idea if this is intentional. 我不知道这是否是故意的。 What's interesting is that there doesn't seem to be a <menu> element defined in current versions of the SVG specification at all; 有趣的是,似乎根本没有在当前版本的SVG规范中定义<menu>元素; it's either been long deprecated or was an extension that's been placed in the wrong namespace. 它要么被长期弃用,要么被放置在错误的命名空间中。 Ugh. 啊。

The easiest workaround might be to use an XSLT stylesheet to remap the <menu> element into another namespace — that's a pretty trivial stylesheet IIRC — and then to register your custom handler to deal with that as you choose (if it is even necessary). 最简单的解决方法可能是使用XSLT样式表将<menu>元素重新映射到另一个命名空间 - 这是一个非常简单的样式表IIRC - 然后注册您的自定义处理程序来处理您选择的(如果它甚至是必要的)。

That's a fine solution for now as I can just run the file through this filter. 这是一个很好的解决方案,因为我可以通过此过滤器运行该文件。 In the nearish future, I will want to be able to have users upload svg files themselves and then it will need to be a little more robust of a solution. 在不久的将来,我希望能够让用户自己上传svg文件,然后需要更加强大的解决方案。 Here is the xslt I created ... 这是我创建的xslt ...

<xsl:stylesheet version="1.0" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <!--Identity Transform.-->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="svg:menu"/>
</xsl:stylesheet>

... and I ran ... ......我跑了......

java -jar /usr/share/java/saxon.jar original.svg svgfix.xslt > fixed.svg

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM