1

大家下午好;

我目前正在开发一个 Java 项目,尝试创建一个桌面工具。我的问题是我现在正在使用框架(plantuml)来获取 svg 格式的图形。但是,我想更改 svg 输出中的现有项目(或我们可以说的组件)并以另一种方式显示它(例如添加细节)。我对此进行了一些研究,发现两个框架可以帮助我实现目标;

1.) http://xmlgraphics.apache.org/batik/ 2.) http://svgsalamander.java.net/

问题; 有没有其他框架可以帮助我操纵现有的 svg?我应该使用哪一个,我应该如何使用我有点迷茫。我不知道从哪里开始。

假设是:我无法改变有关植物的任何事情。所以我只有一个 .svg 格式的图像。

问候 ...

4

2 回答 2

2

我听说过蜡染,我知道它很受欢迎,但我从未使用过它。过去,我不得不在我的程序中以编程方式生成/更改 SVG 几次,无论是在 Java、Javascript 还是 C++ 中。我总是用手做,这意味着:

  • 使用 Java 的标准 org.w3c.dom 或其他一些 DOM 库;
  • 使用 Java 的标准 org.xml.sax 或其他一些 SAX 库。

SVG 是一个 XML 应用程序,因此使用上面列出的两个通用 XML API 非常容易操作。您基本上加载 SVG 文件并通过调用 API 的适当方法开始添加/删除/更改元素。

这是一个使用 SAX for Java 的小例子。我意识到我有点生疏了;该代码似乎可以工作,但欢迎 SAX/XML/Java 大师进行清理。它对使用 Inkscape(矢量编辑程序)生成的 SVG 文件进行操作,但这里讨论的概念适用于任何 SVG(甚至一般的 XML)文档。基本上,它通过改变 XML 元素流来工作;它在图形中的每个对象附近插入一个渐进式标签。

SAX 是基于事件的;在 XML 解析期间引发事件。该代码处理 3 个不同的事件:

  • startDocument在 XML 文档的开头引发;我们使用这个事件来重置累进计数器。
  • startElement在 XML 元素的开头引发;如果元素是路径(在 SVG 中描述形状的常用元素),我们会记下它的位置(cxcy;限定词sodipodi是 Inkscape 的旧名称)。
  • endElement在 XML 元素的末尾引发;如果元素是路径,我们会引发导致标签生成的事件。我们使用 SVG 元素文本将标签添加到文档中。

    import java.io.File;
    import java.io.FileInputStream;
    
    import javax.xml.transform.Result;
    import javax.xml.transform.sax.SAXTransformerFactory;
    import javax.xml.transform.sax.TransformerHandler;
    import javax.xml.transform.stream.StreamResult;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.InputSource;
    import org.xml.sax.SAXException;
    import org.xml.sax.XMLFilter;
    import org.xml.sax.XMLReader;
    import org.xml.sax.helpers.AttributesImpl;
    import org.xml.sax.helpers.XMLFilterImpl;
    import org.xml.sax.helpers.XMLReaderFactory;
    
    public class SVGMod {
    
      public static void main(String argv[]) {
    
        try {
            SAXTransformerFactory factory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
            TransformerHandler serializer = factory.newTransformerHandler();
            Result result = new StreamResult(new File("Output.svg"));
            serializer.setResult(result);
    
            XMLReader reader = XMLReaderFactory.createXMLReader();
            reader.setFeature("http://xml.org/sax/features/namespaces", true);
            reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
    
            XMLFilter filter = new XMLFilterImpl() {
    
                private int x;
                private int y;
                private int cnt;
    
                @Override
                public void startDocument() throws SAXException {
                    super.startDocument();
    
                    cnt = 0;
                }
    
                @Override
                public void startElement(String uri, String localName,
                        String qName, Attributes atts) throws SAXException {
                    super.startElement(uri, localName, qName, atts);
    
                    if (qName.equals("path")) {
                        int xIndex = atts.getIndex("sodipodi:cx");
                        int yIndex = atts.getIndex("sodipodi:cy");
    
                        if (xIndex != -1 && yIndex != -1) {
                            x = (int)Float.parseFloat(atts.getValue(xIndex));
                            y = (int)Float.parseFloat(atts.getValue(yIndex));
                            ++cnt;
                        }
                    }
                }
    
                @Override
                public void endElement(String uri, String localName,
                        String qName) throws SAXException {
                    super.endElement(uri, localName, qName);
    
                    if (qName.equals("path")) {
                        AttributesImpl atts = new AttributesImpl();
                        atts.addAttribute(uri, "", "x", "CDATA", new Integer(x).toString());
                        atts.addAttribute(uri, "", "y", "CDATA", new Integer(y).toString());
                        atts.addAttribute(uri, "", "fill", "CDATA", "red");
                        super.startElement(uri, "", "text", atts);
                        char[] chars = ("Object #: " + cnt).toCharArray();
                        super.characters(chars, 0, chars.length);
                        super.endElement(uri, "", "text");
                    }
                }
            };
            filter.setContentHandler(serializer);
            filter.setParent(reader);
    
            filter.parse(new InputSource(new FileInputStream("Input.svg")));
        } catch (Exception e) {
            e.printStackTrace();
        }
      } 
    }
    
于 2013-02-11T18:04:57.953 回答
0

无论如何,您可能想要修改 PlantUML 路线。在 PlantUML 论坛 * http://sourceforge.net/apps/phpbb/plantuml/viewforum.php?f=1 中,您可以要求一个插件架构,该架构允许按照 PlantUML 修改 svg。这样一来,您的更改将与 PlantUML 所做的相比更加“兼容”,而不是您只进行自己的修改方法。

于 2013-07-28T08:47:49.603 回答