From ab782ee156ff898ced060c551f4f47480fa0cabe Mon Sep 17 00:00:00 2001 From: s_zhangziang Date: Mon, 24 Jun 2024 17:09:06 +0800 Subject: [PATCH 1/3] Added an interface for saving xmlobject objects to zip --- .../org/apache/xmlbeans/FilterXmlObject.java | 5 +++ .../org/apache/xmlbeans/XmlTokenSource.java | 16 +++++++++ .../apache/xmlbeans/impl/store/Cursor.java | 33 +++++++++++++++++++ .../xmlbeans/impl/values/XmlObjectBase.java | 11 +++++++ 4 files changed, 65 insertions(+) diff --git a/src/main/java/org/apache/xmlbeans/FilterXmlObject.java b/src/main/java/org/apache/xmlbeans/FilterXmlObject.java index b0c2cf8c9..95039f2c8 100644 --- a/src/main/java/org/apache/xmlbeans/FilterXmlObject.java +++ b/src/main/java/org/apache/xmlbeans/FilterXmlObject.java @@ -28,6 +28,7 @@ import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.zip.ZipOutputStream; /** * A FilterXmlObject delegates to some other XmlObject, which it can use as @@ -199,6 +200,10 @@ public void save(OutputStream os, XmlOptions options) throws IOException { underlyingXmlObject().save(os, options); } + public void save(ZipOutputStream zos, XmlOptions options) throws IOException { + underlyingXmlObject().save(zos, options); + } + public void save(Writer w, XmlOptions options) throws IOException { underlyingXmlObject().save(w, options); } diff --git a/src/main/java/org/apache/xmlbeans/XmlTokenSource.java b/src/main/java/org/apache/xmlbeans/XmlTokenSource.java index 58aef645b..374288b4a 100644 --- a/src/main/java/org/apache/xmlbeans/XmlTokenSource.java +++ b/src/main/java/org/apache/xmlbeans/XmlTokenSource.java @@ -22,6 +22,7 @@ import javax.xml.stream.XMLStreamReader; import java.io.*; +import java.util.zip.ZipOutputStream; /** * Represents a holder of XML that can return an {@link XmlCursor} @@ -170,6 +171,14 @@ public interface XmlTokenSource { */ void save(OutputStream os) throws IOException; + /** + * Writes the XML represented by this source to the given zip output stream. + * This method will save the XML declaration, including encoding information, + * with the XML. + */ + void save(ZipOutputStream os) throws IOException; + + /** * Writes the XML represented by this source to the given output. * Note that this method does not save the XML declaration, including the encoding information. @@ -336,6 +345,13 @@ public interface XmlTokenSource { */ void save(OutputStream os, XmlOptions options) throws IOException; + /** + * Writes the XML represented by this source to the given zip output stream. + * This method will save the XML declaration, including encoding information, + * with the XML. + */ + void save(ZipOutputStream os, XmlOptions options) throws IOException; + /** * Writes the XML represented by this source to the given output. * Note that this method does not save the XML declaration, including the encoding information. diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java b/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java index 816636858..920bcc9c0 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java @@ -37,6 +37,7 @@ import java.util.Collection; import java.util.Map; import java.util.function.Supplier; +import java.util.zip.ZipOutputStream; public final class Cursor implements XmlCursor, ChangeListener { static final int ROOT = Cur.ROOT; @@ -510,6 +511,10 @@ public void _save(OutputStream os) throws IOException { _save(os, null); } + public void _save(ZipOutputStream zos) throws IOException { + _save(zos, null); + } + public void _save(Writer w) throws IOException { _save(w, null); } @@ -579,6 +584,26 @@ public void _save(OutputStream os, XmlOptions options) throws IOException { } } + public void _save(ZipOutputStream zos, XmlOptions options) throws IOException { + if (zos == null) { + throw new IllegalArgumentException("Null ZipOutputStream specified"); + } + + try (InputStream is = _newInputStream(options)) { + byte[] bytes = new byte[8192]; + + for (; ; ) { + int n = is.read(bytes); + + if (n < 0) { + break; + } + + zos.write(bytes, 0, n); + } + } + } + public void _save(Writer w, XmlOptions options) throws IOException { if (w == null) { throw new IllegalArgumentException("Null Writer specified"); @@ -1975,6 +2000,10 @@ public void save(OutputStream os) throws IOException { syncWrapIOEx(() -> _save(os)); } + public void save(ZipOutputStream zos) throws IOException { + syncWrapIOEx(() -> _save(zos)); + } + public void save(Writer w) throws IOException { syncWrapIOEx(() -> _save(w)); } @@ -2007,6 +2036,10 @@ public void save(OutputStream os, XmlOptions options) throws IOException { syncWrapIOEx(() -> _save(os, options)); } + public void save(ZipOutputStream zos, XmlOptions options) throws IOException { + syncWrapIOEx(() -> _save(zos, options)); + } + public void save(Writer w, XmlOptions options) throws IOException { syncWrapIOEx(() -> _save(w, options)); } diff --git a/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java b/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java index acae8955e..580e7cdaf 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java @@ -35,6 +35,7 @@ import java.util.*; import java.util.function.Function; import java.util.function.IntFunction; +import java.util.zip.ZipOutputStream; public abstract class XmlObjectBase implements TypeStoreUser, Serializable, XmlObject, SimpleValue { public static final short MAJOR_VERSION_NUMBER = (short) 1; // for serialization @@ -191,6 +192,12 @@ public void save(OutputStream os, XmlOptions options) throws IOException { } } + public void save(ZipOutputStream zos, XmlOptions options) throws IOException { + try (XmlCursor cur = newCursorForce()) { + cur.save(zos, makeInnerOptions(options)); + } + } + public void save(Writer w, XmlOptions options) throws IOException { try (XmlCursor cur = newCursorForce()) { cur.save(w, makeInnerOptions(options)); @@ -209,6 +216,10 @@ public void save(OutputStream os) throws IOException { save(os, null); } + public void save(ZipOutputStream zos) throws IOException { + save(zos, null); + } + public void save(Writer w) throws IOException { save(w, null); } From bac17162ab75d2e61e6c241102e55804741baddf Mon Sep 17 00:00:00 2001 From: s_zhangziang Date: Mon, 24 Jun 2024 17:29:57 +0800 Subject: [PATCH 2/3] Added the saveExtraNamespaces Added the saveExtraNamespaces input parameter and modified the top-level element to write to disk to ensure that the top-level element can write extraNamespaces --- .../java/org/apache/xmlbeans/XmlOptions.java | 18 ++++++++ .../org/apache/xmlbeans/impl/store/Saver.java | 42 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/main/java/org/apache/xmlbeans/XmlOptions.java b/src/main/java/org/apache/xmlbeans/XmlOptions.java index 1799da9b5..7ee0272a8 100644 --- a/src/main/java/org/apache/xmlbeans/XmlOptions.java +++ b/src/main/java/org/apache/xmlbeans/XmlOptions.java @@ -107,6 +107,7 @@ public enum XmlOptionsKeys { SAVE_CDATA_LENGTH_THRESHOLD, SAVE_CDATA_ENTITY_COUNT_THRESHOLD, SAVE_SAX_NO_NSDECLS_IN_ATTRIBUTES, + SAVE_EXTRA_NAMESPACES, LOAD_REPLACE_DOCUMENT_ELEMENT, LOAD_STRIP_WHITESPACE, LOAD_STRIP_COMMENTS, @@ -448,6 +449,23 @@ public Map getSaveSuggestedPrefixes() { return (Map) get(XmlOptionsKeys.SAVE_SUGGESTED_PREFIXES); } + /** + * A map of hints to pass to the saver for which prefixes to use + * for which namespace URI. + * + * @param extraNamespaces a map from URIs to prefixes + * @see XmlTokenSource#save(java.io.File, XmlOptions) + * @see XmlTokenSource#xmlText(XmlOptions) + */ + public XmlOptions setSaveExtraNamespaces(Map extraNamespaces) { + return set(XmlOptionsKeys.SAVE_EXTRA_NAMESPACES, extraNamespaces); + } + + @SuppressWarnings("unchecked") + public Map getSaveExtraNamespaces() { + return (Map) get(XmlOptionsKeys.SAVE_EXTRA_NAMESPACES); + } + /** * This option causes the saver to filter a Processing Instruction * with the given target diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java index 14ef6080a..da6767f52 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/Saver.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Saver.java @@ -46,6 +46,9 @@ abstract class Saver { private SaveCur _cur; + protected boolean _isTopLevelElement = true; + protected final Map _extraNamespaces; + private List _ancestorNamespaces; private final Map _suggestedPrefixes; protected XmlOptionCharEscapeMap _replaceChar; @@ -135,6 +138,8 @@ protected void syntheticNamespace(String prefix, String uri, boolean considerDef _suggestedPrefixes = options.getSaveSuggestedPrefixes(); _ancestorNamespaces = _cur.getAncestorNamespaces(); + + _extraNamespaces = options.getSaveExtraNamespaces(); } private static SaveCur createSaveCur(Cur c, XmlOptions options) { @@ -287,10 +292,12 @@ protected final boolean process() { switch (_cur.kind()) { case ROOT: { processRoot(); + _isTopLevelElement = true; break; } case ELEM: { processElement(); + _isTopLevelElement = false; break; } case -ELEM: { @@ -899,6 +906,8 @@ protected boolean emitElement(SaveCur c, List attrNames, List att emitNamespacesHelper(); } + emitExtraNamespacesHelper(); + for (int i = 0; i < attrNames.size(); i++) { emitAttrHelper(attrNames.get(i), attrValues.get(i)); } @@ -943,6 +952,17 @@ protected void emitXmlns(String prefix, String uri) { emit('"'); } + private void emitExtraNamespacesHelper() { + if (!_isTopLevelElement || null == _extraNamespaces) + return; + + for (Map.Entry nsEntry : _extraNamespaces.entrySet()) { + emit(' '); + emitXmlns(nsEntry.getKey(), nsEntry.getValue()); + } + + } + private void emitNamespacesHelper() { LinkedHashMap nsMap = new LinkedHashMap<>(); for (iterateMappings(); hasMapping(); nextMapping()) { @@ -1853,6 +1873,8 @@ protected boolean emitElement(SaveCur c, List attrNames, List att emit('<'); emitName(c.getName(), false); + emitExtraNamespacesHelper(); + for (int i = 0; i < attrNames.size(); i++) { emitAttrHelper(attrNames.get(i), attrValues.get(i)); } @@ -1902,6 +1924,15 @@ private void emitNamespacesHelper() { } } + private void emitExtraNamespacesHelper() { + if (!_isTopLevelElement || null == _extraNamespaces) + return; + for (Map.Entry nsEntry : _extraNamespaces.entrySet()) { + emit(' '); + emitXmlns(nsEntry.getKey(), nsEntry.getValue()); + } + } + private void emitAttrHelper(QName attrName, String attrValue) { emit(' '); emitName(attrName, true); @@ -2578,6 +2609,15 @@ private String getPrefixedName(QName name) { return prefix + ":" + local; } + private void emitExtraNamespacesHelper() { + if (!_isTopLevelElement || null == _extraNamespaces|| !_nsAsAttrs) + return; + for (Map.Entry nsEntry : _extraNamespaces.entrySet()) { + String prefix = nsEntry.getKey(); + _attributes.addAttribute("http://www.w3.org/2000/xmlns/", prefix, "xmlns:" + prefix , "CDATA", nsEntry.getValue()); + } + } + private void emitNamespacesHelper() { for (iterateMappings(); hasMapping(); nextMapping()) { String prefix = mappingPrefix(); @@ -2607,6 +2647,8 @@ protected boolean emitElement(SaveCur c, List attrNames, List att emitNamespacesHelper(); } + emitExtraNamespacesHelper(); + for (int i = 0; i < attrNames.size(); i++) { QName name = attrNames.get(i); From 16af8f6835744054f7069af8e1f1bb4b06b9447c Mon Sep 17 00:00:00 2001 From: s_zhangziang Date: Mon, 24 Jun 2024 17:33:19 +0800 Subject: [PATCH 3/3] Separate two PRs --- .../org/apache/xmlbeans/FilterXmlObject.java | 5 --- .../org/apache/xmlbeans/XmlTokenSource.java | 16 --------- .../apache/xmlbeans/impl/store/Cursor.java | 33 ------------------- .../xmlbeans/impl/values/XmlObjectBase.java | 11 ------- 4 files changed, 65 deletions(-) diff --git a/src/main/java/org/apache/xmlbeans/FilterXmlObject.java b/src/main/java/org/apache/xmlbeans/FilterXmlObject.java index 95039f2c8..b0c2cf8c9 100644 --- a/src/main/java/org/apache/xmlbeans/FilterXmlObject.java +++ b/src/main/java/org/apache/xmlbeans/FilterXmlObject.java @@ -28,7 +28,6 @@ import java.util.Calendar; import java.util.Date; import java.util.List; -import java.util.zip.ZipOutputStream; /** * A FilterXmlObject delegates to some other XmlObject, which it can use as @@ -200,10 +199,6 @@ public void save(OutputStream os, XmlOptions options) throws IOException { underlyingXmlObject().save(os, options); } - public void save(ZipOutputStream zos, XmlOptions options) throws IOException { - underlyingXmlObject().save(zos, options); - } - public void save(Writer w, XmlOptions options) throws IOException { underlyingXmlObject().save(w, options); } diff --git a/src/main/java/org/apache/xmlbeans/XmlTokenSource.java b/src/main/java/org/apache/xmlbeans/XmlTokenSource.java index 374288b4a..58aef645b 100644 --- a/src/main/java/org/apache/xmlbeans/XmlTokenSource.java +++ b/src/main/java/org/apache/xmlbeans/XmlTokenSource.java @@ -22,7 +22,6 @@ import javax.xml.stream.XMLStreamReader; import java.io.*; -import java.util.zip.ZipOutputStream; /** * Represents a holder of XML that can return an {@link XmlCursor} @@ -171,14 +170,6 @@ public interface XmlTokenSource { */ void save(OutputStream os) throws IOException; - /** - * Writes the XML represented by this source to the given zip output stream. - * This method will save the XML declaration, including encoding information, - * with the XML. - */ - void save(ZipOutputStream os) throws IOException; - - /** * Writes the XML represented by this source to the given output. * Note that this method does not save the XML declaration, including the encoding information. @@ -345,13 +336,6 @@ public interface XmlTokenSource { */ void save(OutputStream os, XmlOptions options) throws IOException; - /** - * Writes the XML represented by this source to the given zip output stream. - * This method will save the XML declaration, including encoding information, - * with the XML. - */ - void save(ZipOutputStream os, XmlOptions options) throws IOException; - /** * Writes the XML represented by this source to the given output. * Note that this method does not save the XML declaration, including the encoding information. diff --git a/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java b/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java index 920bcc9c0..816636858 100755 --- a/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java +++ b/src/main/java/org/apache/xmlbeans/impl/store/Cursor.java @@ -37,7 +37,6 @@ import java.util.Collection; import java.util.Map; import java.util.function.Supplier; -import java.util.zip.ZipOutputStream; public final class Cursor implements XmlCursor, ChangeListener { static final int ROOT = Cur.ROOT; @@ -511,10 +510,6 @@ public void _save(OutputStream os) throws IOException { _save(os, null); } - public void _save(ZipOutputStream zos) throws IOException { - _save(zos, null); - } - public void _save(Writer w) throws IOException { _save(w, null); } @@ -584,26 +579,6 @@ public void _save(OutputStream os, XmlOptions options) throws IOException { } } - public void _save(ZipOutputStream zos, XmlOptions options) throws IOException { - if (zos == null) { - throw new IllegalArgumentException("Null ZipOutputStream specified"); - } - - try (InputStream is = _newInputStream(options)) { - byte[] bytes = new byte[8192]; - - for (; ; ) { - int n = is.read(bytes); - - if (n < 0) { - break; - } - - zos.write(bytes, 0, n); - } - } - } - public void _save(Writer w, XmlOptions options) throws IOException { if (w == null) { throw new IllegalArgumentException("Null Writer specified"); @@ -2000,10 +1975,6 @@ public void save(OutputStream os) throws IOException { syncWrapIOEx(() -> _save(os)); } - public void save(ZipOutputStream zos) throws IOException { - syncWrapIOEx(() -> _save(zos)); - } - public void save(Writer w) throws IOException { syncWrapIOEx(() -> _save(w)); } @@ -2036,10 +2007,6 @@ public void save(OutputStream os, XmlOptions options) throws IOException { syncWrapIOEx(() -> _save(os, options)); } - public void save(ZipOutputStream zos, XmlOptions options) throws IOException { - syncWrapIOEx(() -> _save(zos, options)); - } - public void save(Writer w, XmlOptions options) throws IOException { syncWrapIOEx(() -> _save(w, options)); } diff --git a/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java b/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java index 580e7cdaf..acae8955e 100644 --- a/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java +++ b/src/main/java/org/apache/xmlbeans/impl/values/XmlObjectBase.java @@ -35,7 +35,6 @@ import java.util.*; import java.util.function.Function; import java.util.function.IntFunction; -import java.util.zip.ZipOutputStream; public abstract class XmlObjectBase implements TypeStoreUser, Serializable, XmlObject, SimpleValue { public static final short MAJOR_VERSION_NUMBER = (short) 1; // for serialization @@ -192,12 +191,6 @@ public void save(OutputStream os, XmlOptions options) throws IOException { } } - public void save(ZipOutputStream zos, XmlOptions options) throws IOException { - try (XmlCursor cur = newCursorForce()) { - cur.save(zos, makeInnerOptions(options)); - } - } - public void save(Writer w, XmlOptions options) throws IOException { try (XmlCursor cur = newCursorForce()) { cur.save(w, makeInnerOptions(options)); @@ -216,10 +209,6 @@ public void save(OutputStream os) throws IOException { save(os, null); } - public void save(ZipOutputStream zos) throws IOException { - save(zos, null); - } - public void save(Writer w) throws IOException { save(w, null); }