我正在尝试读取从旧程序导出的较大(1 MB)svg文件。我无权访问此程序或数据。我只有这个导出的svg文件,我可能不得不从这个源定期导入一个新导出的svg文件。我发现使用蜡染的第一个问题是它在读取此文件时非常严格。例如,Firefox在读取和显示此文件时没有问题。 Batik(包括Squiggle因文档中的某些“自定义”标签而无法显示)。我得到的例外是......
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)
...所以使用不完全有用的链接Writing a batik Dom Extension我设法编写以下内容......
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() );
}
但是我得到了同样的错误,System.out.println()声明从未被命中,所以它显然没有正确注册我的工厂。另外一点就是要让Batik不那么严格,以便它只是像Firefox一样跳过它不理解的东西?
答案 0 :(得分:1)
调查表明Batik 1.7.0 implementation不允许您创建拦截SVG名称空间中元素的DOM扩展;它会抛出异常,否则会导致查找已注册工厂的代码。我不知道这是否是故意的。
有趣的是,在SVG specification的当前版本中似乎没有定义<menu>
元素;它要么被长期弃用,要么被放置在错误的命名空间中。啊。
最简单的解决方法可能是使用XSLT样式表将<menu>
元素重新映射到另一个命名空间 - 这是一个非常简单的样式表IIRC - 然后注册您的自定义处理程序来处理您选择的(如果它甚至是必要的。)
答案 1 :(得分:1)
这是一个很好的解决方案,因为我可以通过此过滤器运行文件。在不久的将来,我希望能够让用户自己上传svg文件,然后需要更加强大的解决方案。这是我创建的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>
......我跑了......
java -jar /usr/share/java/saxon.jar original.svg svgfix.xslt > fixed.svg