This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new ab34489  plc4j: switch xml writer to a stax based implementation to 
align to the reader
ab34489 is described below

commit ab34489c435f552369c0d602a394fafab546f54c
Author: Sebastian Rühl <[email protected]>
AuthorDate: Tue Apr 20 18:33:25 2021 +0200

    plc4j: switch xml writer to a stax based implementation to align to the 
reader
---
 plc4j/drivers/s7/src/test/java/S7IoTest.java       | 106 +++++++++---------
 .../java/spi/generation/WriteBufferXmlBased.java   | 122 +++++++++++++--------
 2 files changed, 132 insertions(+), 96 deletions(-)

diff --git a/plc4j/drivers/s7/src/test/java/S7IoTest.java 
b/plc4j/drivers/s7/src/test/java/S7IoTest.java
index a96e27c..ee2a43c 100644
--- a/plc4j/drivers/s7/src/test/java/S7IoTest.java
+++ b/plc4j/drivers/s7/src/test/java/S7IoTest.java
@@ -42,59 +42,59 @@ public class S7IoTest {
     void TestS7MessageBytes() throws Exception {
         String wantXml =
             "<TPKTPacket>\n" +
-                "    <protocolId bitLength=\"8\" 
dataType=\"uint8\">3</protocolId>\n" +
-                "    <reserved bitLength=\"8\" 
dataType=\"uint8\">0</reserved>\n" +
-                "    <len bitLength=\"16\" dataType=\"uint16\">29</len>\n" +
-                "    <COTPPacket>\n" +
-                "        <headerLength bitLength=\"8\" 
dataType=\"uint18\">5</headerLength>\n" +
-                "        <tpduCode bitLength=\"8\" 
dataType=\"uint8\">240</tpduCode>\n" +
-                "        <COTPPacketData>\n" +
-                "            <eot bitLength=\"1\" 
dataType=\"bit\">false</eot>\n" +
-                "            <tpduRef bitLength=\"7\" 
dataType=\"uint8\">13</tpduRef>\n" +
-                "        </COTPPacketData>\n" +
-                "        <parameters>\n" +
-                "            <COTPParameter>\n" +
-                "                <parameterType bitLength=\"8\" 
dataType=\"uint8\">192</parameterType>\n" +
-                "                <parameterLength bitLength=\"8\" 
dataType=\"uint8\">1</parameterLength>\n" +
-                "                <COTPParameterTpduSize>\n" +
-                "                    <COTPTpduSize bitLength=\"8\" 
dataType=\"uint8\" stringRepresentation=\"SIZE_4096\">12</COTPTpduSize>\n" +
-                "                </COTPParameterTpduSize>\n" +
-                "            </COTPParameter>\n" +
-                "        </parameters>\n" +
-                "        <S7Message>\n" +
-                "            <protocolId bitLength=\"8\" 
dataType=\"uint8\">50</protocolId>\n" +
-                "            <messageType bitLength=\"8\" 
dataType=\"uint8\">3</messageType>\n" +
-                "            <reserved bitLength=\"16\" 
dataType=\"uint16\">0</reserved>\n" +
-                "            <tpduReference bitLength=\"16\" 
dataType=\"uint16\">11</tpduReference>\n" +
-                "            <parameterLength bitLength=\"16\" 
dataType=\"uint16\">2</parameterLength>\n" +
-                "            <payloadLength bitLength=\"16\" 
dataType=\"uint16\">5</payloadLength>\n" +
-                "            <S7MessageResponseData>\n" +
-                "                <errorClass bitLength=\"8\" 
dataType=\"uint8\">0</errorClass>\n" +
-                "                <errorCode bitLength=\"8\" 
dataType=\"uint8\">0</errorCode>\n" +
-                "            </S7MessageResponseData>\n" +
-                "            <S7Parameter>\n" +
-                "                <parameterType bitLength=\"8\" 
dataType=\"uint8\">4</parameterType>\n" +
-                "                <S7ParameterReadVarResponse>\n" +
-                "                    <numItems bitLength=\"8\" 
dataType=\"uint8\">1</numItems>\n" +
-                "                </S7ParameterReadVarResponse>\n" +
-                "            </S7Parameter>\n" +
-                "            <S7Payload>\n" +
-                "                <S7PayloadReadVarResponse>\n" +
-                "                    <items>\n" +
-                "                        <S7VarPayloadDataItem>\n" +
-                "                            <DataTransportErrorCode 
bitLength=\"8\" dataType=\"uint8\" 
stringRepresentation=\"OK\">255</DataTransportErrorCode>\n" +
-                "                            <DataTransportSize 
bitLength=\"8\" dataType=\"uint8\" 
stringRepresentation=\"BIT\">3</DataTransportSize>\n" +
-                "                            <dataLength bitLength=\"16\" 
dataType=\"uint16\">1</dataLength>\n" +
-                "                            <data>\n" +
-                "                                <value bitLength=\"8\" 
dataType=\"int8\">1</value>\n" +
-                "                            </data>\n" +
-                "                            <padding></padding>\n" +
-                "                        </S7VarPayloadDataItem>\n" +
-                "                    </items>\n" +
-                "                </S7PayloadReadVarResponse>\n" +
-                "            </S7Payload>\n" +
-                "        </S7Message>\n" +
-                "    </COTPPacket>\n" +
+                "  <protocolId dataType=\"uint8\" 
bitLength=\"8\">3</protocolId>\n" +
+                "  <reserved dataType=\"uint8\" 
bitLength=\"8\">0</reserved>\n" +
+                "  <len dataType=\"uint16\" bitLength=\"16\">29</len>\n" +
+                "  <COTPPacket>\n" +
+                "    <headerLength dataType=\"uint8\" 
bitLength=\"8\">5</headerLength>\n" +
+                "    <tpduCode dataType=\"uint8\" 
bitLength=\"8\">240</tpduCode>\n" +
+                "    <COTPPacketData>\n" +
+                "      <eot dataType=\"bit\" bitLength=\"1\">false</eot>\n" +
+                "      <tpduRef dataType=\"uint8\" 
bitLength=\"7\">13</tpduRef>\n" +
+                "    </COTPPacketData>\n" +
+                "    <parameters>\n" +
+                "      <COTPParameter>\n" +
+                "        <parameterType dataType=\"uint8\" 
bitLength=\"8\">192</parameterType>\n" +
+                "        <parameterLength dataType=\"uint8\" 
bitLength=\"8\">1</parameterLength>\n" +
+                "        <COTPParameterTpduSize>\n" +
+                "          <COTPTpduSize dataType=\"int8\" bitLength=\"8\" 
stringRepresentation=\"SIZE_4096\">12</COTPTpduSize>\n" +
+                "        </COTPParameterTpduSize>\n" +
+                "      </COTPParameter>\n" +
+                "    </parameters>\n" +
+                "    <S7Message>\n" +
+                "      <protocolId dataType=\"uint8\" 
bitLength=\"8\">50</protocolId>\n" +
+                "      <messageType dataType=\"uint8\" 
bitLength=\"8\">3</messageType>\n" +
+                "      <reserved dataType=\"uint16\" 
bitLength=\"16\">0</reserved>\n" +
+                "      <tpduReference dataType=\"uint16\" 
bitLength=\"16\">11</tpduReference>\n" +
+                "      <parameterLength dataType=\"uint16\" 
bitLength=\"16\">2</parameterLength>\n" +
+                "      <payloadLength dataType=\"uint16\" 
bitLength=\"16\">5</payloadLength>\n" +
+                "      <S7MessageResponseData>\n" +
+                "        <errorClass dataType=\"uint8\" 
bitLength=\"8\">0</errorClass>\n" +
+                "        <errorCode dataType=\"uint8\" 
bitLength=\"8\">0</errorCode>\n" +
+                "      </S7MessageResponseData>\n" +
+                "      <S7Parameter>\n" +
+                "        <parameterType dataType=\"uint8\" 
bitLength=\"8\">4</parameterType>\n" +
+                "        <S7ParameterReadVarResponse>\n" +
+                "          <numItems dataType=\"uint8\" 
bitLength=\"8\">1</numItems>\n" +
+                "        </S7ParameterReadVarResponse>\n" +
+                "      </S7Parameter>\n" +
+                "      <S7Payload>\n" +
+                "        <S7PayloadReadVarResponse>\n" +
+                "          <items>\n" +
+                "            <S7VarPayloadDataItem>\n" +
+                "              <DataTransportErrorCode dataType=\"uint8\" 
bitLength=\"8\" stringRepresentation=\"OK\">255</DataTransportErrorCode>\n" +
+                "              <DataTransportSize dataType=\"uint8\" 
bitLength=\"8\" stringRepresentation=\"BIT\">3</DataTransportSize>\n" +
+                "              <dataLength dataType=\"uint16\" 
bitLength=\"16\">1</dataLength>\n" +
+                "              <data>\n" +
+                "                <value dataType=\"int8\" 
bitLength=\"8\">1</value>\n" +
+                "              </data>\n" +
+                "              <padding></padding>\n" +
+                "            </S7VarPayloadDataItem>\n" +
+                "          </items>\n" +
+                "        </S7PayloadReadVarResponse>\n" +
+                "      </S7Payload>\n" +
+                "    </S7Message>\n" +
+                "  </COTPPacket>\n" +
                 "</TPKTPacket>\n";
 
 
diff --git 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferXmlBased.java
 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferXmlBased.java
index 4b2b8b7..f052054 100644
--- 
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferXmlBased.java
+++ 
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferXmlBased.java
@@ -19,36 +19,42 @@
 
 package org.apache.plc4x.java.spi.generation;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
+
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.*;
+
 import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.Stack;
 
 public class WriteBufferXmlBased implements WriteBuffer {
 
-    Stack<Element> stack;
+    Stack<String> stack;
+
+    ByteArrayOutputStream byteArrayOutputStream;
 
-    Document document;
+    XMLEventFactory xmlEventFactory;
+
+    XMLEventWriter xmlEventWriter;
 
     int pos = 1;
 
+    int depth = 0;
+
     public WriteBufferXmlBased() {
-        DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();
+        byteArrayOutputStream = new ByteArrayOutputStream();
+        XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
+        xmlEventFactory = XMLEventFactory.newInstance();
         try {
-            this.document = 
documentBuilderFactory.newDocumentBuilder().newDocument();
-        } catch (ParserConfigurationException e) {
+            xmlEventWriter = 
xmlOutputFactory.createXMLEventWriter(byteArrayOutputStream);
+        } catch (XMLStreamException e) {
             throw new PlcRuntimeException(e);
         }
         this.stack = new Stack<>();
@@ -56,12 +62,21 @@ public class WriteBufferXmlBased implements WriteBuffer {
 
     @Override
     public int getPos() {
-        return pos/8;
+        return pos / 8;
     }
 
     @Override
     public void pushContext(String logicalName) {
-        stack.push(document.createElement(logicalName));
+        try {
+            indent();
+            depth++;
+            StartElement startElement = xmlEventFactory.createStartElement("", 
"", logicalName);
+            xmlEventWriter.add(startElement);
+            newLine();
+        } catch (XMLStreamException e) {
+            throw new PlcRuntimeException(e);
+        }
+        stack.push(logicalName);
     }
 
     @Override
@@ -161,33 +176,33 @@ public class WriteBufferXmlBased implements WriteBuffer {
 
     @Override
     public void popContext(String logicalName) {
-        Element currentContext = stack.pop();
-        if (!currentContext.getTagName().equals(logicalName)) {
-            throw new PlcRuntimeException("Unexpected pop context '" + 
currentContext.getTagName() + '\'');
+        try {
+            depth--;
+            indent();
+            EndElement endElement = xmlEventFactory.createEndElement("", "", 
logicalName);
+            xmlEventWriter.add(endElement);
+            newLine();
+        } catch (XMLStreamException e) {
+            throw new PlcRuntimeException(e);
+        }
+
+        String context = stack.pop();
+        if (!context.equals(logicalName)) {
+            throw new PlcRuntimeException("Unexpected pop context '" + context 
+ '\'');
         }
         if (stack.isEmpty()) {
-            document.appendChild(currentContext);
-            return;
+            try {
+                xmlEventWriter.close();
+            } catch (XMLStreamException e) {
+                throw new PlcRuntimeException(e);
+            }
         }
-        stack.peek().appendChild(currentContext);
     }
 
     public String getXmlString() {
         try {
-            Transformer transformer = 
TransformerFactory.newInstance().newTransformer();
-            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
-            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
-            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, 
"yes");
-            //transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, 
"roles.dtd");
-            
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount";, "4");
-
-            ByteArrayOutputStream byteArrayOutputStream = new 
ByteArrayOutputStream();
-            transformer.transform(new DOMSource(document),
-                new StreamResult(byteArrayOutputStream));
-
-            return byteArrayOutputStream.toString();
-        } catch (TransformerException e) {
+            return byteArrayOutputStream.toString("UTF-8");
+        } catch (UnsupportedEncodingException e) {
             throw new PlcRuntimeException(e);
         }
     }
@@ -196,12 +211,33 @@ public class WriteBufferXmlBased implements WriteBuffer {
         pos += bits;
     }
 
+    private void newLine() throws XMLStreamException {
+        Characters newLine = xmlEventFactory.createCharacters("\n");
+        xmlEventWriter.add(newLine);
+    }
+
+    private void indent() throws XMLStreamException {
+        Characters indent = 
xmlEventFactory.createCharacters(StringUtils.repeat("  ", depth));
+        xmlEventWriter.add(indent);
+    }
+
     private void createAndAppend(String logicalName, String dataType, int 
bitLength, String data) {
-        Element element = 
document.createElement(sanitizeLogicalName(logicalName));
-        element.setAttribute("dataType", dataType);
-        element.setAttribute("bitLength", String.valueOf(bitLength));
-        element.appendChild(document.createTextNode(data));
-        stack.peek().appendChild(element);
+        try {
+            indent();
+            StartElement startElement = xmlEventFactory.createStartElement("", 
"", sanitizeLogicalName(logicalName));
+            xmlEventWriter.add(startElement);
+            Attribute dataTypeAttribute = 
xmlEventFactory.createAttribute("dataType", dataType);
+            xmlEventWriter.add(dataTypeAttribute);
+            Attribute bitLengthAttribute = 
xmlEventFactory.createAttribute("bitLength", String.valueOf(bitLength));
+            xmlEventWriter.add(bitLengthAttribute);
+            Characters dataCharacters = xmlEventFactory.createCharacters(data);
+            xmlEventWriter.add(dataCharacters);
+            EndElement endElement = xmlEventFactory.createEndElement("", "", 
sanitizeLogicalName(logicalName));
+            xmlEventWriter.add(endElement);
+            newLine();
+        } catch (XMLStreamException e) {
+            throw new PlcRuntimeException(e);
+        }
     }
 
     private String sanitizeLogicalName(String logicalName) {

Reply via email to