Java创建<a> element in SVG DOM</a>

时间:2014-06-19 23:08:20

标签: parsing dom svg sax batik

我创建了一个Java应用程序来修改一些SVG文件。 这是我的问题: 我想在SVG文件的DOM中添加一个元素,以在矩形上创建链接。 SVG文件是从另一个应用程序生成的。 我需要用Java来做。

所以这就是我所做的:

  • 我使用JASXP尝试解析和修改我的SVG文件。

我尝试了很多配置,使用SAX,DOM API来解析它,这是我成功从SVG文件创建文档的唯一方法。

这是我的SVGFile:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.0//EN'
      'http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd'>
<svg ... xmlns:xlink="http://www.w3.org/1999/xlink" ....xmlns="http://www.w3.org/2000/svg" ...>
<!--Generated by the Batik Graphics2D SVG Generator-->
<defs id="genericDefs"/>
<g>
  <defs id="defs1">
   ....define the clipath...
  </defs>

  HERE I WOULD LIKE TO INSERT OPEN A ELEMENT : <a ....>
  <g font-size="11" transform="translate(2,212)" fill-opacity="1"fill="rgb(192,255,255)" text-rendering="geometricPrecision" font-family="sans-serif" stroke="rgb(192,255,255)" font-weight="bold" stroke-opacity="1">
     <rect x="0" width="80" height="40" y="0" clip-path="url(#clipPath1)" stroke="none"/>
  </g>
  <g font-size="11" stroke-linecap="butt" transform="translate(2,212)" fill-opacity="1" fill="black" text-rendering="geometricPrecision" font-family="sans-serif" stroke-linejoin="round" stroke="black" font-weight="bold" stroke-opacity="1" stroke-miterlimit="0">
      <rect fill="none" x="0" width="80" height="40" y="0" clip-path="url(#clipPath1)"/>
 </g>
 <g font-size="11" transform="translate(2,212)" fill-opacity="1" fill="black" text-rendering="geometricPrecision" font-family="sans-serif" stroke="black" font-weight="bold" stroke-opacity="1">
      <text x="28" xml:space="preserve" y="12" clip-path="url(#clipPath4)"stroke="none" >Titre</text>
      <line y2="12" fill="none" x1="28" clip-path="url(#clipPath4)" x2="52" y1="12"/>       
 </g>
</g>
</svg>
 AND I WOULD LIKE TO CLOSE IT here : </a>

从我的SVG获取DOM文档的代码:

        String parser = XMLResourceDescriptor.getXMLParserClassName();
        SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);

        File file = new File ("D:/mySVGFile.svg");
        String uri = file.toURI().toString();

        Document doc = f.createDocument(uri); 

要解析文档获取我做到了:

           Element racine = doc.getDocumentElement();
       String tag ="text";    // Because it's the only element I have store in an Array

    NodeList liste = doc.getElementsByTagName(tag);

        Element e = (Element) liste.item(0);    // element text = Titre
        Node target = e.getParentNode().getParentNode().getParentNode();
        Element link = doc.createElement("a"); 
        link.setAttribute("xlink:href", "DestinationFile.svg#67");
        target.insertBefore(link, target);

以下是控制台错误:

    org.w3c.dom.DOMException: The child node (type: 1, name: svg) is missing.
at org.apache.batik.dom.AbstractNode.createDOMException(AbstractNode.java:408)
at org.apache.batik.dom.AbstractParentNode.insertBefore(AbstractParentNode.java:78)
at SAXTagCount.main(SAXTagCount.java:60)

实际上我真的不知道如何在Java中为SVG文件创建这个元素。

先谢谢你的帮助!

吉姆

2 个答案:

答案 0 :(得分:1)

该行

Element link = doc.createElement("a");

不正确。要创建SVG <a>元素,或者实际上任何svg元素,您必须使用createElementNS即。

Element link = doc.createElementNS("http://www.w3.org/2000/svg", "a");

您的其他一个问题是您有太多的getParentNode()调用。文本元素的父级是其封闭的<g>。其父级是另一个<g>,其父级是<svg>根元素,因此您的insertBefore尝试在<a>根元素之前插入<svg>,而不是<g>允许。在我看来,你需要删除2个getParentNode()调用,将它放在正确的级别。

您还有其他各种问题,例如在正确的位置插入 - 不知何故,您需要找到<a>元素,理想情况下,它会有ID或某种方式来识别它,否则您会有去搜索它。此外,您还需要收集您想要制作成<a>个孩子的所有元素。您可以通过使用link.appendChild重新显示每个现有元素来使其成为target.insertBefore(link, target); 元素的子元素。但是,在一个答案中可以涵盖很多。

{{1}}

无效,因为您无法使用目标两次。论证应该是目标的孩子,而不是目标本身。

答案 1 :(得分:0)

/**
 * 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);
}