java – 如何加载和解析SVG文档
背景
有许多与阅读和解析SVG路径相关的未解答的问题: > Easiest way to read in svg path data with Java? 这个问题和答案旨在解决所有这些问题. 问题 SVG路径元素包含data attribute(d).有时需要从SVG文件中加载,解析和提取路径信息. 题 如何使用Java从SVG文件加载,解析和提取SVG路径信息? 解决方法
概观
使用Apache Batik加载和解析SVG文件.该解决方案在将SVG文件转换为MetaPost的初步阶段显示Java代码.这应该提供有关如何使用Java从SVG文件加载,解析和提取内容的一般概念. 图书馆 您将需要以下库: batik-anim.jar batik-awt-util.jar batik-bridge.jar batik-css.jar batik-dom.jar batik-ext.jar batik-gvt.jar batik-parser.jar batik-script.jar batik-svg-dom.jar batik-svggen.jar batik-util.jar batik-xml.jar xml-apis-ext.jar 加载SVG文件 主应用程序将SVG文件加载到DOM中,然后将DOM转换为SVG DOM. initSVGDOM()方法调用非常重要.在不调用initSVGDOM()的情况下,从DOM中提取SVG DOM元素的方法将不可用. import java.io.File; import java.io.IOException; import java.net.URI; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.DocumentLoader; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.bridge.UserAgent; import org.apache.batik.bridge.UserAgentAdapter; import org.apache.batik.dom.svg.SAXSVGDocumentFactory; import org.apache.batik.dom.svg.SVGOMSVGElement; import org.apache.batik.util.XMLResourceDescriptor; import org.w3c.dom.Document; import org.w3c.dom.NodeList; /** * Responsible for converting all SVG path elements into MetaPost curves. */ public class SVGMetaPost { private static final String PATH_ELEMENT_NAME = "path"; private Document svgDocument; /** * Creates an SVG Document given a URI. * * @param uri Path to the file. * @throws Exception Something went wrong parsing the SVG file. */ public SVGMetaPost( String uri ) throws IOException { setSVGDocument( createSVGDocument( uri ) ); } /** * Finds all the path nodes and converts them to MetaPost code. */ public void run() { NodeList pathNodes = getPathElements(); int pathNodeCount = pathNodes.getLength(); for( int iPathNode = 0; iPathNode < pathNodeCount; iPathNode++ ) { MetaPostPath mpp = new MetaPostPath( pathNodes.item( iPathNode ) ); System.out.println( mpp.toCode() ); } } /** * Returns a list of elements in the SVG document with names that * match PATH_ELEMENT_NAME. * * @return The list of "path" elements in the SVG document. */ private NodeList getPathElements() { return getSVGDocumentRoot().getElementsByTagName( PATH_ELEMENT_NAME ); } /** * Returns an SVGOMSVGElement that is the document's root element. * * @return The SVG document typecast into an SVGOMSVGElement. */ private SVGOMSVGElement getSVGDocumentRoot() { return (SVGOMSVGElement)getSVGDocument().getDocumentElement(); } /** * This will set the document to parse. This method also initializes * the SVG DOM enhancements,which are necessary to perform SVG and CSS * manipulations. The initialization is also required to extract information * from the SVG path elements. * * @param document The document that contains SVG content. */ public void setSVGDocument( Document document ) { initSVGDOM( document ); this.svgDocument = document; } /** * Returns the SVG document parsed upon instantiating this class. * * @return A valid,parsed,non-null SVG document instance. */ public Document getSVGDocument() { return this.svgDocument; } /** * Enhance the SVG DOM for the given document to provide CSS- and SVG-specific * DOM interfaces. * * @param document The document to enhance. * @link http://wiki.apache.org/xmlgraphics-batik/BootSvgAndCssDom */ private void initSVGDOM( Document document ) { UserAgent userAgent = new UserAgentAdapter(); DocumentLoader loader = new DocumentLoader( userAgent ); BridgeContext bridgeContext = new BridgeContext( userAgent,loader ); bridgeContext.setDynamicState( BridgeContext.DYNAMIC ); // Enable CSS- and SVG-specific enhancements. (new GVTBuilder()).build( bridgeContext,document ); } /** * Use the SAXSVGDocumentFactory to parse the given URI into a DOM. * * @param uri The path to the SVG file to read. * @return A Document instance that represents the SVG file. * @throws Exception The file could not be read. */ private Document createSVGDocument( String uri ) throws IOException { String parser = XMLResourceDescriptor.getXMLParserClassName(); SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory( parser ); return factory.createDocument( uri ); } /** * Reads a file and parses the path elements. * * @param args args[0] - Filename to parse. * @throws IOException Error reading the SVG file. */ public static void main( String args[] ) throws IOException { URI uri = new File( args[0] ).toURI(); SVGMetaPost converter = new SVGMetaPost( uri.toString() ); converter.run(); } } 注意:除非另有说明,否则调用initSVGDOM()应该是Batik的默认行为.唉,它不是,发现这个宝石意味着在他们的网站上阅读documentation buried. 解析SVG DOM 解析SVG DOM是相对微不足道的. toCode()方法是该类的主力: import org.apache.batik.dom.svg.SVGItem; import org.apache.batik.dom.svg.SVGOMPathElement; import org.w3c.dom.Node; import org.w3c.dom.svg.SVGPathSegList; /** * Responsible for converting an SVG path element to MetaPost. This * will convert just the bezier curve portion of the path element,not * its style. Typically the SVG path data is provided from the "d" attribute * of an SVG path node. */ public class MetaPostPath extends MetaPost { private SVGOMPathElement pathElement; /** * Use to create an instance of a class that can parse an SVG path * element to produce MetaPost code. * * @param pathNode The path node containing a "d" attribute (output as MetaPost code). */ public MetaPostPath( Node pathNode ) { setPathNode( pathNode ); } /** * Converts this object's SVG path to a MetaPost draw statement. * * @return A string that represents the MetaPost code for a path element. */ public String toCode() { StringBuilder sb = new StringBuilder( 16384 ); SVGOMPathElement pathElement = getPathElement(); SVGPathSegList pathList = pathElement.getNormalizedPathSegList(); int pathObjects = pathList.getNumberOfItems(); sb.append( ( new MetaPostComment( getId() ) ).toString() ); for( int i = 0; i < pathObjects; i++ ) { SVGItem item = (SVGItem)pathList.getItem( i ); sb.append( String.format( "%s%n",item.getValueAsString() ) ); } return sb.toString(); } /** * Returns the value for the id attribute of the path element. If the * id isn't present,this will probably throw a NullPointerException. * * @return A non-null,but possibly empty String. */ private String getId() { return getPathElement().getAttributes().getNamedItem( "id" ).getNodeValue(); } /** * Typecasts the given pathNode to an SVGOMPathElement for later analysis. * * @param pathNode The path element that contains curves,lines,and other * SVG instructions. */ private void setPathNode( Node pathNode ) { this.pathElement = (SVGOMPathElement)pathNode; } /** * Returns an SVG document element that contains path instructions (usually * for drawing on a canvas). * * @return An object that contains a list of items representing pen * movements. */ private SVGOMPathElement getPathElement() { return this.pathElement; } } 建立 编译因环境而异.类似于以下的脚本应该有所帮助: #!/bin/bash mkdir -p ./build javac -cp ./lib/* -d ./build ./source/*.java 确保将所有.jar文件放入./lib目录中.将源文件放入./source目录. 跑 创建一个脚本(或批处理文件)来执行该程序: #!/bin/bash java -cp ./lib/*:./build SVGMetaPost $1 产量 对包含有效SVG路径的文件运行时,会产生: $./run.sh stripe/trigon.svg % path8078-6 M 864.1712 779.3069 C 864.1712 779.3069 868.04065 815.6211 871.4032 833.4621 C 873.4048 844.08203 874.91724 855.0544 879.0846 864.82227 C 884.24023 876.9065 895.2377 887.9899 900.0184 897.3661 C 904.7991 906.7422 907.3466 918.3257 907.3466 918.3257 C 907.3466 918.3257 892.80817 887.6536 864.1712 887.3086 C 835.53424 886.9637 820.9958 918.3257 820.9958 918.3257 C 820.9958 918.3257 823.6176 906.59644 828.32404 897.3661 C 833.0304 888.1356 844.10223 876.9065 849.2578 864.82227 C 853.4252 855.05444 854.9376 844.08203 856.93915 833.4621 C 860.3017 815.6211 864.17114 779.3069 864.17114 779.3069 z 从这里开始,应该清楚如何使用Java将SVG路径数据读入相应的SVG对象. 附录 请注意,从SVG转换为MetaPost的最简单方法是: >将SVG转换为PDF(例如,使用Inkscape或rsvg-convert). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |