如何使用 java 读取/写入压缩的 mxGraph 图
How to read / write compressed mxGraph diagram with java
我必须阅读和修改一些使用 draw.io(现在 diagrams.net)创建的图表。它们看起来像:
<mxfile pages="1" version="11.1.5"><diagram id="aC-2Vsr7-bsXYD2UCZoz" name="Page-1">zZRNT4QwEEB/DXdo1/24uup60MRkDx5Nl45QLQwpXQF/vWXbAs2KejJ7Ie2bKZ15bRrRbdHuFKvyR+QgIxLzNqI3ESGb5cp8e9BZsNisLciU4BYlI9iLT3AwdvQoONRBokaUWlQhTLEsIdUBY0phE6a9ogx3rVgGZ2CfMnlOnwXXuaVrshr5PYgs9zsny42NFMwnu07qnHFsJojeRnSrELUdFe0WZO/Oe7Hr7maiQ2EKSv3NAjy89T5ILNnBHMkp4UlhCnWNhrrlp+CL0HPxypIHUb6781vFxIZ8IWToZaix1p33p/BYcuhTk4heN7nQsK9Y2kcbc2EMy3UhXfi8JVfGBygN7QS5/XaABWjVmRQX9ba7cNqMZ5d4lk/ObekYc9clG348GjUD16GfOsd/8U1+8U3mfdPQN71k30l8EcLpT7bpjOqrxN96r3px0arX/6baTMd36pQ6eezp7Rc=</diagram></mxfile>
很明显,它们是用 deflate() javascript 函数编码和压缩的。如何使用 Java 解压缩它们?我在 mxUtils 中找不到任何有用的方法来读取压缩图,并且 mxXmlUtils.parseXml(xmlDiagram) 似乎只能解析普通的 text/xml.
通过mxGraph修改后API,如何重新编码压缩图表?
有人知道如何做到这一点吗?
提前致谢!
----根据Thomas的回答修改---
Thomas,您的代码完美无缺!但我还需要 'invert' 它来编码和压缩图表。我试图以相反的顺序进行相同的操作,但似乎放气操作或 Base64 编码以某种方式破坏了图表。以下是我的代码:
//url encoding...
String xmlGraphEncoded = URLEncoder.encode(xmlGraphString, "UTF-8");
xmlGraphEncoded=xmlGraphEncoded.replace("+", "%20");
byte[] bytesToCompress=xmlGraphEncoded.getBytes("UTF-8");
//deflating...
//Deflater deflater = new Deflater(); << do not use this
Deflater deflater = new Deflater(9,true);
deflater.setInput(bytesToCompress);
deflater.finish();
int compressedSize=deflater.deflate(bytesToCompress);
//encoding B64...
compressedEncodedBytes= Base64.encodeBase64(bytesToCompress);
我知道第一个编码效果很好,但在 deflate&Base64 之后,draw-io 转换工具抱怨这个错误:“inflateRaw 失败:无效的存储块长度”
你能帮帮我吗?
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URLDecoder;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import org.apache.commons.codec.binary.Base64;
public mxGraphModel diagramStringToGraphModel(String diagramString) throws IOException
{
if (Base64.isBase64(diagramString))
{
byte[] bytes = Base64.decodeBase64(diagramString);
byte[] buffer = new byte[1024];
Inflater inflater = new Inflater(true);
inflater.setInput(bytes);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (InflaterInputStream iis = new InflaterInputStream(new ByteArrayInputStream(bytes), inflater))
{
int bytesRead = 0;
while ((bytesRead = iis.read(buffer)) != -1)
{
bos.write(buffer, 0, bytesRead);
}
}
diagramString = new String(bos.toByteArray());
}
String str = URLDecoder.decode(diagramString, "UTF-8");
Document doc = xmlUtils.parseXml(str);
mxCodec codec = new mxCodec(doc);
return (mxGraphModel) codec.decode(doc.getDocumentElement());
}
XMLUtils.java
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.xml.sax.InputSource;
public synchronized DocumentBuilder getDocumentBuilder()
{
if (documentBuilder == null)
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
dbf.setXIncludeAware(false);
dbf.setValidating(false);
try
{
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
}
catch (ParserConfigurationException e)
{
log.log(Level.SEVERE, "Failed to set feature", e);
}
try
{
documentBuilder = dbf.newDocumentBuilder();
}
catch (Exception e)
{
log.log(Level.SEVERE, "Failed to construct a document builder", e);
}
}
return documentBuilder;
}
public synchronized Document parseXml(String xml)
{
try
{
return getDocumentBuilder().parse(new InputSource(new StringReader(xml)));
}
catch (Exception e)
{
log.log(Level.SEVERE, "Failed to parse XML", e);
}
return null;
}
我必须阅读和修改一些使用 draw.io(现在 diagrams.net)创建的图表。它们看起来像:
<mxfile pages="1" version="11.1.5"><diagram id="aC-2Vsr7-bsXYD2UCZoz" name="Page-1">zZRNT4QwEEB/DXdo1/24uup60MRkDx5Nl45QLQwpXQF/vWXbAs2KejJ7Ie2bKZ15bRrRbdHuFKvyR+QgIxLzNqI3ESGb5cp8e9BZsNisLciU4BYlI9iLT3AwdvQoONRBokaUWlQhTLEsIdUBY0phE6a9ogx3rVgGZ2CfMnlOnwXXuaVrshr5PYgs9zsny42NFMwnu07qnHFsJojeRnSrELUdFe0WZO/Oe7Hr7maiQ2EKSv3NAjy89T5ILNnBHMkp4UlhCnWNhrrlp+CL0HPxypIHUb6781vFxIZ8IWToZaix1p33p/BYcuhTk4heN7nQsK9Y2kcbc2EMy3UhXfi8JVfGBygN7QS5/XaABWjVmRQX9ba7cNqMZ5d4lk/ObekYc9clG348GjUD16GfOsd/8U1+8U3mfdPQN71k30l8EcLpT7bpjOqrxN96r3px0arX/6baTMd36pQ6eezp7Rc=</diagram></mxfile>
很明显,它们是用 deflate() javascript 函数编码和压缩的。如何使用 Java 解压缩它们?我在 mxUtils 中找不到任何有用的方法来读取压缩图,并且 mxXmlUtils.parseXml(xmlDiagram) 似乎只能解析普通的 text/xml.
通过mxGraph修改后API,如何重新编码压缩图表?
有人知道如何做到这一点吗?
提前致谢!
----根据Thomas的回答修改---
Thomas,您的代码完美无缺!但我还需要 'invert' 它来编码和压缩图表。我试图以相反的顺序进行相同的操作,但似乎放气操作或 Base64 编码以某种方式破坏了图表。以下是我的代码:
//url encoding...
String xmlGraphEncoded = URLEncoder.encode(xmlGraphString, "UTF-8");
xmlGraphEncoded=xmlGraphEncoded.replace("+", "%20");
byte[] bytesToCompress=xmlGraphEncoded.getBytes("UTF-8");
//deflating...
//Deflater deflater = new Deflater(); << do not use this
Deflater deflater = new Deflater(9,true);
deflater.setInput(bytesToCompress);
deflater.finish();
int compressedSize=deflater.deflate(bytesToCompress);
//encoding B64...
compressedEncodedBytes= Base64.encodeBase64(bytesToCompress);
我知道第一个编码效果很好,但在 deflate&Base64 之后,draw-io 转换工具抱怨这个错误:“inflateRaw 失败:无效的存储块长度”
你能帮帮我吗?
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URLDecoder;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import org.apache.commons.codec.binary.Base64;
public mxGraphModel diagramStringToGraphModel(String diagramString) throws IOException
{
if (Base64.isBase64(diagramString))
{
byte[] bytes = Base64.decodeBase64(diagramString);
byte[] buffer = new byte[1024];
Inflater inflater = new Inflater(true);
inflater.setInput(bytes);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (InflaterInputStream iis = new InflaterInputStream(new ByteArrayInputStream(bytes), inflater))
{
int bytesRead = 0;
while ((bytesRead = iis.read(buffer)) != -1)
{
bos.write(buffer, 0, bytesRead);
}
}
diagramString = new String(bos.toByteArray());
}
String str = URLDecoder.decode(diagramString, "UTF-8");
Document doc = xmlUtils.parseXml(str);
mxCodec codec = new mxCodec(doc);
return (mxGraphModel) codec.decode(doc.getDocumentElement());
}
XMLUtils.java
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.xml.sax.InputSource;
public synchronized DocumentBuilder getDocumentBuilder()
{
if (documentBuilder == null)
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
dbf.setXIncludeAware(false);
dbf.setValidating(false);
try
{
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
}
catch (ParserConfigurationException e)
{
log.log(Level.SEVERE, "Failed to set feature", e);
}
try
{
documentBuilder = dbf.newDocumentBuilder();
}
catch (Exception e)
{
log.log(Level.SEVERE, "Failed to construct a document builder", e);
}
}
return documentBuilder;
}
public synchronized Document parseXml(String xml)
{
try
{
return getDocumentBuilder().parse(new InputSource(new StringReader(xml)));
}
catch (Exception e)
{
log.log(Level.SEVERE, "Failed to parse XML", e);
}
return null;
}