转换SVG时Batik出错:元素<use>的属性“xlink:href”是必需的

时间:2018-01-30 11:33:02

标签: java svg batik

我有一个SVG文件,结构如下:

<svg xmlns="http://www.w3.org/2000/svg" width="506px" height="261px" viewBox="0 0 506 261" style="overflow: hidden; display: block; width: 506px; height: 261px;">
   <defs>
      <path fill="none" stroke="rgb(211,211,211)" d="M 5,-5 L 0,0 L 5,5" stroke-opacity="1" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" id="ygc10_0" />
      <path fill="none" stroke="rgb(211,211,211)" d="M 5,-5 L 0,0 L 5,5" stroke-opacity="1" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" id="ygc10_1" />
      <path fill="none" stroke="rgb(211,211,211)" d="M 5,-5 L 0,0 L 5,5" stroke-opacity="1" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" id="ygc10_2" />
      <path fill="none" stroke="rgb(211,211,211)" d="M 5,-5 L 0,0 L 5,5" stroke-opacity="1" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" id="ygc10_3" />
      <path fill="none" stroke="rgb(211,211,211)" d="M 5,-5 L 0,0 L 5,5" stroke-opacity="1" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" id="ygc10_4" />
   </defs>
   <g style="pointer-events:visiblePainted" transform="translate(-57.822952932363535 -41.05614567526554)" image-rendering="auto" shape-rendering="auto">
      <g>
         <path fill="none" stroke="rgb(211,211,211)" d="M 257.9119715596548,73.05614567526554 L 257.9119715596548,135.06828972638465" stroke-opacity="1" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" />
         <use href="#ygc10_0" transform="matrix(0 -2 2 0 257.912 135.068)" style="pointer-events: none;" />
      </g>
      <g>
         <path fill="none" stroke="rgb(211,211,211)" d="M 107.82295293236353,207.4377203121161 L 107.82295293236353,261.03014731718906" stroke-opacity="1" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" />
         <use href="#ygc10_1" transform="matrix(0 -2 2 0 107.823 261.03)" style="pointer-events: none;" />
      </g>
...

我正在尝试从ByteArrayInputStream生成一个PNG,就像这样(请不要考虑现在没有例外处理):

static ByteArrayOutputStream svgToPng(ByteArrayInputStream streamBytes) throws TranscoderException, IOException {
    PNGTranscoder t = new PNGTranscoder();

    TranscoderInput input = new TranscoderInput(streamBytes);
    ByteArrayOutputStream ostream = new ByteArrayOutputStream();
    TranscoderOutput output = new TranscoderOutput(ostream);

    t.transcode(input, output);

    ostream.flush();
    return ostream;
}

但是,我在transcode()的调用中获得了异常:

org.apache.batik.bridge.BridgeException: null:-1
The attribute "xlink:href" of the element <use> is required
    at org.apache.batik.bridge.SVGUseElementBridge.buildCompositeGraphicsNode(Unknown Source)
    at org.apache.batik.bridge.SVGUseElementBridge.createGraphicsNode(Unknown Source)
    at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source)
    at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source)
    at org.apache.batik.bridge.GVTBuilder.buildGraphicsNode(Unknown Source)
    at org.apache.batik.bridge.GVTBuilder.buildComposite(Unknown Source)
...
你能帮帮我吗?在PNGTranscoder声明之后我也尝试了:

t.addTranscodingHint(SVGAbstractTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI,
                SVGDOMImplementation.SVG_NAMESPACE_URI);

但没有效果。谢谢大家。

2 个答案:

答案 0 :(得分:1)

您的SVG文件无效,修复它的一种方法是在根SVG元素上添加xmlns:xlink属性,如此...

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink" 
     width="506px" height="261px" viewBox="0 0 506 261">

由于Paul指出你还需要将href属性更改为xlink:href,因为href是SVG 2而Batik还不支持。

答案 1 :(得分:0)

INFO:在我的情况下,生成SVG字符串没有宽度值。因此它引发了异常。

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
                  Process: com.example.omkar.rainforest, PID: 3950
                  java.lang.RuntimeException: An error occurred while executing doInBackground()
                      at android.os.AsyncTask$3.done(AsyncTask.java:309)
                      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                      at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                      at java.lang.Thread.run(Thread.java:818)
                   Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)
                      at java.net.InetAddress.lookupHostByName(InetAddress.java:464)
                      at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
                      at java.net.InetAddress.getAllByName(InetAddress.java:215)
                      at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29)
                      at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188)
                      at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157)
                      at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100)
                      at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357)
                      at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340)
                      at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330)
                      at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
                      at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433)
                      at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114)
                      at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
                      at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java)
                      at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:746)
                      at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:722)
                      at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:306)
                      at org.jsoup.helper.HttpConnection.get(HttpConnection.java:295)
                      at com.example.omkar.rainforest.MainActivity$Weather.doInBackground(MainActivity.java:65)
                      at com.example.omkar.rainforest.MainActivity$Weather.doInBackground(MainActivity.java:57)
                      at android.os.AsyncTask$2.call(AsyncTask.java:295)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                      at java.lang.Thread.run(Thread.java:818) 
                   Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
                      at libcore.io.Posix.android_getaddrinfo(Native Method)
                      at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)
                      at java.net.InetAddress.lookupHostByName(InetAddress.java:451)
                      at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252) 
                      at java.net.InetAddress.getAllByName(InetAddress.java:215) 
                      at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29) 
                      at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188) 
                      at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157) 
                      at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100) 
                      at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357) 
                      at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340) 
                      at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330) 
                      at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248) 
                      at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433) 
                      at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114) 
                      at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 
                      at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java) 
                      at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:746) 
                      at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:722) 
                      at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:306) 
                      at org.jsoup.helper.HttpConnection.get(HttpConnection.java:295) 
                      at com.example.omkar.rainforest.MainActivity$Weather.doInBackground(MainActivity.java:65) 
                      at com.example.omkar.rainforest.MainActivity$Weather.doInBackground(MainActivity.java:57) 
                      at android.os.AsyncTask$2.call(AsyncTask.java:295) 
                      at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                      at java.lang.Thread.run(Thread.java:818) 
                   Caused by: android.system.ErrnoException: android_getaddrinfo failed: EACCES (Permission denied)
                      at libcore.io.Posix.android_getaddrinfo(Native Method) 
                      at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55) 
                      at java.net.InetAddress.lookupHostByName(InetAddress.java:451) 
                      at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252) 
                      at java.net.InetAddress.getAllByName(InetAddress.java:215) 
                      at com.android.okhttp.internal.Network$1.resolveInetAddresses(Network.java:29) 
                      at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:188) 
                      at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:157) 
                      at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:100) 
                      at com.android.okhttp.internal.http.HttpEngine.createNextConnection(HttpEngine.java:357) 
                      at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:340) 
                      at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:330) 
                      at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:248) 
                      at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:433) 
                      at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:114) 
                      at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89) 
                      at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java) 
                      at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:746) 
                      at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:722) 
                      at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:306) 
                      at org.jsoup.helper.HttpConnection.get(HttpConnection.java:295) 
                      at com.example.omkar.rainforest.MainActivity$Weather.doInBackground(MainActivity.java:65) 
                      at com.example.omkar.rainforest.MainActivity$Weather.doInBackground(MainActivity.java:57) 
                      at android.os.AsyncTask$2.call(AsyncTask.java:295) 
                      at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                      at java.lang.Thread.run(Thread.java:818) 
E/Surface: getSlotFromBufferLocked: unknown buffer: 0xaa3fc950
D/OpenGLRenderer: endAllStagingAnimators on 0xa284da80 (RippleDrawable) with handle 0xa283eaa0
I/Choreographer: Skipped 188 frames!  The application may be doing too much work on its main thread.
Application terminated.

应该像

<g transform="translate(�, 85.00)  scale(�)">
相关问题