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

olabusayoT pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git


The following commit(s) were added to refs/heads/main by this push:
     new 4821837d3 Change TDMLRunner to use XMLTextInfosetInputter/Outputter as 
default
4821837d3 is described below

commit 4821837d3373444516cf02a7c0483b223ea1dce9
Author: olabusayoT <[email protected]>
AuthorDate: Thu Apr 2 15:54:20 2026 -0400

    Change TDMLRunner to use XMLTextInfosetInputter/Outputter as default
    
    - Replaced `TDMLInfosetOutputterScala` with `TDMLInfosetOutputterXML`.
    - Update TDML Schema to add support for custom validation name/type and use 
in stringAsXML tests
    - Drop whitespace between elements to keep expected matching actual, but 
keep all others like mixed whitespace, attributes, comments unchanged
    - Introduced tests for `stringAsXML` validation and namespace handling.
    - Enhanced `DaffodilXMLLoader` and related classes with `removeComments` 
and `removeProcInstr` flags
    - Add `TestStringAsXmlValidator` with a unified validator for namespace and 
non-namespace cases.
    - Add getScalaResult for `TDMLInfosetOutputterAll`
    - add clarifying info to TDMLInfosetInputter TDML Exceptions in case of 
non-matches
    - undo type aware changes for ScalaXMLInfosetOutputter (the way it was 
adding namespace bindings for scalaXML was not exactly correct as it wasn't 
part of the child element's minimized scope. We found it would be too much 
trouble to implement correctly for scalaXML, so we decided to remove the 
functionality)
    - ensure stringAsXml file line endings are not normalized in windows
    - change generic exception to InvalidInfosetException
    - Adjusted `.gitattributes` to prevent line ending normalization for 
specific test files.
    - Verify prefixes resolve to the same namespaces when checking prefixes
    - NullInfosetInputter should be receiving UTF-8 bytes for its events
    
    Deprecation/Compatibility
    - Instead of ScalaXMLInfosetInputter/Outputter being the default 
inputter/outputter for TDML Runner, it is now XMLTextInfosetInputter/Outputter 
since it supports stringsAsXml feature
    - We check the actual infoset for the presence of 
XMLTextInfoset.stringAsXML(currently stringAsXML) and don't normalize CRLF to 
LF in for that element
    
    DAFFODIL-2909
---
 .gitattributes                                     |   6 +-
 .../resources/org/apache/daffodil/xsd/tdml.xsd     |  20 ++-
 .../lib/xml/DaffodilConstructingLoader.scala       |  39 +++--
 .../daffodil/lib/xml/DaffodilXMLLoader.scala       |  31 ++--
 .../org/apache/daffodil/lib/xml/XMLUtils.scala     | 166 +++++++++++++++++----
 .../infoset/ScalaXMLInfosetOutputter.scala         |  25 +---
 .../daffodil/lib/xml/test/unit/TestXMLLoader.scala |  14 +-
 .../daffodil/lib/xml/test/unit/TestXMLUtils.scala  |  11 ++
 .../org/apache/daffodil/tdml/TDMLRunner.scala      |   8 +-
 .../processor/tdml/DaffodilTDMLDFDLProcessor.scala |  24 ++-
 .../processor/tdml/TDMLInfosetInputter.scala       |  49 ++++--
 .../processor/tdml/TDMLInfosetOutputter.scala      |  51 ++++---
 .../org/apache/daffodil/cliTest/TestCLITdml.scala  |   2 +-
 ...apache.daffodil.api.validation.ValidatorFactory |  16 ++
 .../org/apache/daffodil/infoset/stringAsXML.tdml   |  98 ++++++++++++
 .../stringAsXml/namespaced/binMessage_01.dat       | Bin 821 -> 790 bytes
 .../stringAsXml/namespaced/binMessage_01.dat.xml   |   2 +-
 .../namespaced/binMessage_01.dat.xml.dat           | Bin 776 -> 790 bytes
 ...inMessage_01.dat.xml.dat => binMessage_01a.dat} | Bin 776 -> 930 bytes
 ...inMessage_01.dat.xml => binMessage_01a.dat.xml} |  15 +-
 .../stringAsXml/namespaced/xsd/binMessage.dfdl.xsd |  28 +++-
 .../namespaced/xsd/binMessageWithXmlPayload.xsd    |  27 ++++
 .../namespaced/xsd/stringAsXmlWrapper.xsd          |  12 ++
 .../stringAsXml/namespaced/xsd/xmlPayload.xsd      |   8 +
 .../daffodil/section07/variables/variables_01.tdml |   2 +-
 .../daffodil/infoset/TestStringAsXmlTDML.scala     |  38 +++++
 .../infoset/TestStringAsXmlValidator.scala         |  50 +++++++
 project/Rat.scala                                  |   6 +
 28 files changed, 607 insertions(+), 141 deletions(-)

diff --git a/.gitattributes b/.gitattributes
index b49c2777e..9a8401f7f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -14,4 +14,8 @@
 # limitations under the License.
 
 # Do not include KEYS in archived source releases
-/KEYS export-ignore 
+/KEYS export-ignore
+# ensure stringAsXml file line endings are not normalized in windows
+/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
 -text
+/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat.xml
 -text
+/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/nonamespace/binMessage_01.dat.xml
 -text
\ No newline at end of file
diff --git a/daffodil-core/src/main/resources/org/apache/daffodil/xsd/tdml.xsd 
b/daffodil-core/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
index 8a8441a1e..0b6397666 100644
--- a/daffodil-core/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
+++ b/daffodil-core/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
@@ -224,11 +224,21 @@
   </simpleType>
 
   <simpleType name="validationType">
-    <restriction base="xs:token">
-      <enumeration value="on"/>
-      <enumeration value="limited"/>
-      <enumeration value="off"/>
-    </restriction>
+    <union>
+      <simpleType>
+        <restriction base="xs:token">
+          <enumeration value="on"/>
+          <enumeration value="limited"/>
+          <enumeration value="off"/>
+        </restriction>
+      </simpleType>
+
+      <simpleType>
+        <restriction base="xs:token">
+          <pattern value="[A-Za-z0-9_]+"/>
+        </restriction>
+      </simpleType>
+    </union>
   </simpleType>
 
   <element name="document" type="tns:documentType"/>
diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilConstructingLoader.scala
 
b/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilConstructingLoader.scala
index 8c1af3f61..a8c97963c 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilConstructingLoader.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilConstructingLoader.scala
@@ -94,13 +94,16 @@ object Position {
  *                          behavior of normalizing CRLF to LF, and solitary 
CR to LF.
  *                          Defaults to true. Should only be changed in 
special circumstances
  *                          as not normalizing CRLFs is non-standard for XML.
- *
+ * @param removeComments True to remove comments. This is used to keep the XML 
as close to the original as possible
+ * @param removeProcInstr True to remove processing instructions. This is used 
to keep the XML as close to the original as possible
  */
 class DaffodilConstructingLoader private[xml] (
   uri: URI,
   errorHandler: org.xml.sax.ErrorHandler,
   addPositionAttributes: Boolean,
-  normalizeCRLFtoLF: Boolean
+  normalizeCRLFtoLF: Boolean,
+  removeComments: Boolean,
+  removeProcInstr: Boolean
 ) extends ConstructingParser(
     {
       // Note: we must open the XML carefully since it might be in some non
@@ -122,7 +125,14 @@ class DaffodilConstructingLoader private[xml] (
     errorHandler: org.xml.sax.ErrorHandler,
     addPositionAttributes: Boolean = false
   ) =
-    this(uri, errorHandler, addPositionAttributes, normalizeCRLFtoLF = true)
+    this(
+      uri,
+      errorHandler,
+      addPositionAttributes,
+      normalizeCRLFtoLF = true,
+      removeComments = true,
+      removeProcInstr = true
+    )
 
   /**
    * Ensures that DOCTYPES aka DTDs, if encountered, are rejected.
@@ -316,19 +326,30 @@ class DaffodilConstructingLoader private[xml] (
   }
 
   /**
-   * Drops comments
+   * Drops comments if removeComments is true
+   *
+   * This is optional controlled by a constructor parameter.
    */
   override def comment(pos: Int, s: String): Comment = {
-    // returning null drops comments
-    null
+    if (removeComments) {
+      // returning null drops comments
+      null
+    } else {
+      super.comment(pos, s)
+    }
   }
 
   /**
-   * Drops processing instructions
+   * Drops processing instructions if removeProcInstr is false
+   *
+   * This is optional controlled by a constructor parameter.
    */
   override def procInstr(pos: Int, target: String, txt: String) = {
-    // returning null drops processing instructions
-    null
+    if (removeProcInstr) { // returning null drops processing instructions
+      null
+    } else {
+      super.procInstr(pos, target, txt)
+    }
   }
 
   private def parseXMLPrologAttributes(
diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilXMLLoader.scala
 
b/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilXMLLoader.scala
index 0b32d1acc..c250dfcd0 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilXMLLoader.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/DaffodilXMLLoader.scala
@@ -702,31 +702,20 @@ class DaffodilXMLLoader(val errorHandler: 
org.xml.sax.ErrorHandler)
    * @param optSchemaURI Optional URI for XML schema for the XML source 
document.
    * @param addPositionAttributes True to add dafint:file dafint:line 
attributes to all elements.
    *                              Defaults to false.
-   * @return an scala.xml.Node (Element actually) which is the document 
element of the source.
-   */
-  def load(
-    source: DaffodilSchemaSource,
-    optSchemaURI: Option[URI],
-    addPositionAttributes: Boolean = false
-  ): scala.xml.Node =
-    load(source, optSchemaURI, addPositionAttributes, normalizeCRLFtoLF = true)
-
-  /**
-   * package private constructor gives access to normalizeCRLFtoLF feature.
-   *
-   * @param source The URI for the XML document which may be a XML or DFDL 
schema, or just XML data.
-   * @param optSchemaURI Optional URI for XML schema for the XML source 
document.
-   * @param addPositionAttributes True to add dafint:file dafint:line 
attributes to all elements.
-   *                              Defaults to false.
    * @param normalizeCRLFtoLF True to normalize CRLF and isolated CR to LF. 
This should usually be true,
    *                          but some special case situations may require 
preservation of CRLF/CR.
+   * @param removeComments True to remove comments. This is used to keep the 
XML as close to the original as possible
+   * @param removeProcInstr True to remove processing instructions. This is 
used to keep the XML as close to the original as possible
+   *
    * @return an scala.xml.Node (Element actually) which is the document 
element of the source.
    */
-  private[xml] def load(
+  def load(
     source: DaffodilSchemaSource,
     optSchemaURI: Option[URI],
-    addPositionAttributes: Boolean,
-    normalizeCRLFtoLF: Boolean
+    addPositionAttributes: Boolean = false,
+    normalizeCRLFtoLF: Boolean = true,
+    removeComments: Boolean = true,
+    removeProcInstr: Boolean = true
   ): scala.xml.Node = {
     //
     // First we invoke the validator to explicitly validate the XML against
@@ -819,7 +808,9 @@ class DaffodilXMLLoader(val errorHandler: 
org.xml.sax.ErrorHandler)
         source.uriForLoading,
         errorHandler,
         addPositionAttributes,
-        normalizeCRLFtoLF
+        normalizeCRLFtoLF,
+        removeComments,
+        removeProcInstr
       )
     val res =
       try {
diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/XMLUtils.scala 
b/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/XMLUtils.scala
index da67ac01b..d2a817912 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/XMLUtils.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/lib/xml/XMLUtils.scala
@@ -42,6 +42,8 @@ import org.apache.daffodil.lib.iapi.URISchemaSource
 import org.apache.daffodil.lib.schema.annotation.props.LookupLocation
 import org.apache.daffodil.lib.util.Maybe
 import org.apache.daffodil.lib.util.Misc
+import org.apache.daffodil.runtime1.infoset.InvalidInfosetException
+import org.apache.daffodil.runtime1.infoset.XMLTextInfoset
 
 import org.apache.commons.io.IOUtils
 import org.xml.sax.XMLReader
@@ -599,6 +601,7 @@ object XMLUtils {
 
   def removeComments(e: Node): Node = {
     e match {
+      case x: Elem if isStringAsXmlElem(x) => x
       case Elem(prefix, label, attribs, scope, child*) => {
         val newChildren = child.filterNot { _.isInstanceOf[Comment] }.map { 
removeComments(_) }
         Elem(prefix, label, attribs, scope, true, newChildren*)
@@ -638,40 +641,108 @@ object XMLUtils {
     res
   }
 
+  private def isStringAsXmlElem(ns: Node): Boolean = {
+    ns match {
+      case e @ Elem(
+            null,
+            XMLTextInfoset.stringAsXml,
+            Null,
+            NamespaceBinding(null, null | "", _),
+            _*
+          ) =>
+        true
+      case _ => false
+    }
+  }
+
+  /**
+   * normalizes CRLF to LF within text nodes in non-stringAsXML elements
+   *
+   * Some fields in infosets could contain LFs, but could be changed to CRLF
+   * in Windows due to git's autocrlf feature. And since infoset outputters
+   * always output LF we need to undo with git might do and normalize those 
CRLF's
+   * to LF.
+   */
+  private def normalizeCRLFtoLF(ns: Node): Node = {
+    ns match {
+      // NOTE: this is specifically for the stringAsXml feature as we avoid
+      // making changes to any of its children requiring that stringAsXml in
+      // the infoset match results exactly.
+      case e: Elem if isStringAsXmlElem(e) => e
+      case e: Elem => {
+        val children = e.child
+        val normalized = children.map(normalizeCRLFtoLF)
+        val res = {
+          if (normalized eq children) e
+          else e.copy(child = normalized)
+        }
+        res
+      }
+      case Text(data) if data.contains("\r") => {
+        val replaced = data.replaceAll("\r\n", "\n").replaceAll("\r", "\n")
+        Text(replaced)
+      }
+      case _ => ns
+    }
+  }
+
   /**
    * removes insignificant whitespace from between elements
    */
 
   private def removeMixedWhitespace(ns: Node): Node = {
-    if (!ns.isInstanceOf[Elem]) return ns
-    val e = ns.asInstanceOf[Elem]
-    val children = e.child
-    val noMixedChildren =
-      if (children.exists(_.isInstanceOf[Elem])) {
-        children
-          .filter {
-            case Text(data) if data.matches("""\s*""") => false
-            case Text(data) =>
-              throw new Exception("Element %s contains mixed data: 
%s".format(e.label, data))
-            case _ => true
-          }
-          .map(removeMixedWhitespace)
-      } else {
-        children.filter {
-          //
-          // So this is a bit strange, but we're dropping nodes that are Empty 
String.
-          //
-          // In XML we cannot tell <foo></foo> where there is a Text("") 
child, from <foo></foo> with Nil children
-          //
-          case Text("") => false // drop empty strings
-          case _ => true
+    ns match {
+      // NOTE: this is specifically for the stringAsXml feature as we avoid
+      // making changes to any of its children except removing any surrounding
+      // whitespace, requiring that stringAsXml in the infoset match results 
exactly.
+      case e: Elem if isStringAsXmlElem(e) => {
+        val (elemChildren, nonElemChildren) = e.child.partition {
+          _.isInstanceOf[Elem]
+        }
+        if (elemChildren.length != 1)
+          throw new InvalidInfosetException("stringAsXml must contain a single 
child element.")
+        nonElemChildren.foreach {
+          case Text(data) if data.matches("""\s*""") => // no-op, empty text 
siblings are fine
+          case x =>
+            throw new Exception(
+              "%s is some kind of mixed content not allowed as a stringAsXml 
child".format(x)
+            )
         }
+        e.asInstanceOf[Elem].copy(child = elemChildren)
       }
+      case e: Elem => {
+        val children = e.child
+        val noMixedChildren =
+          if (children.exists(_.isInstanceOf[Elem])) {
+            children
+              .filter {
+                case Text(data) if data.matches("""\s*""") => false
+                case Text(data) =>
+                  throw new Exception(
+                    "Element %s contains mixed data: %s".format(e.label, data)
+                  )
+                case _ => true
+              }
+              .map(removeMixedWhitespace)
+          } else {
+            children.filter {
+              //
+              // So this is a bit strange, but we're dropping nodes that are 
Empty String.
+              //
+              // In XML we cannot tell <foo></foo> where there is a Text("") 
child, from <foo></foo> with Nil children
+              //
+              case Text("") => false // drop empty strings
+              case _ => true
+            }
+          }
 
-    val res =
-      if (noMixedChildren eq children) e
-      else e.copy(child = noMixedChildren)
-    res
+        val res =
+          if (noMixedChildren eq children) e
+          else e.copy(child = noMixedChildren)
+        res
+      }
+      case _ => ns
+    }
   }
 
   /**
@@ -700,6 +771,15 @@ object XMLUtils {
   ): NodeSeq = {
     val res = n match {
 
+      case e @ Elem(
+            null,
+            XMLTextInfoset.stringAsXml,
+            Null,
+            NamespaceBinding(null, null | "", _),
+            _*
+          ) =>
+        e
+
       case e @ Elem(prefix, label, attributes, scope, children*) => {
 
         val filteredScope = if (ns.length > 0) filterScope(scope, ns) else 
xml.TopScope
@@ -808,7 +888,8 @@ object XMLUtils {
     val noPCData = convertPCDataToText(noComments)
     val combinedText = coalesceAllAdjacentTextNodes(noPCData)
     val noMixedWS = removeMixedWhitespace(combinedText)
-    noMixedWS
+    val noCRLFs = normalizeCRLFtoLF(noMixedWS)
+    noCRLFs
   }
 
   class XMLDifferenceException(message: String) extends Exception(message)
@@ -973,6 +1054,15 @@ Differences were (path, expected, actual):
         } else if (checkPrefixes && prefixA != prefixB) {
           // different prefix
           List((zPath + "/" + labelA + "@prefix", prefixA, prefixB))
+        } else if (checkPrefixes && a.scope.getURI(prefixA) != 
b.scope.getURI(prefixB)) {
+          // prefixes doesn't resolve to same namespace
+          List(
+            (
+              zPath + "/" + labelA + "@prefix-namespace",
+              a.scope.getURI(prefixA),
+              b.scope.getURI(prefixB)
+            )
+          )
         } else if (checkNamespaces && mappingsA != mappingsB) {
           // different namespace bindings
           List((zPath + "/" + labelA + "@xmlns", mappingsA, mappingsB))
@@ -1055,6 +1145,28 @@ Differences were (path, expected, actual):
           computeTextDiff(zPath, tA, tB, maybeType, maybeFloatEpsilon, 
maybeDoubleEpsilon)
         thisDiff
       }
+      case (cA: Comment, cB: Comment) => {
+        val thisDiff = computeTextDiff(
+          zPath + "/@comment",
+          cA.toString,
+          cB.toString,
+          None,
+          None,
+          None
+        )
+        thisDiff
+      }
+      case (pcA: PCData, pcB: PCData) => {
+        val thisDiff = computeTextDiff(
+          zPath + "/@PCDATA",
+          pcA.toString,
+          pcB.toString,
+          None,
+          None,
+          None
+        )
+        thisDiff
+      }
       case (pA: ProcInstr, pB: ProcInstr) => {
         val ProcInstr(tA1label, tA1content) = pA
         val ProcInstr(tB1label, tB1content) = pB
diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/infoset/ScalaXMLInfosetOutputter.scala
 
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/infoset/ScalaXMLInfosetOutputter.scala
index 4abe32f37..e30534fcc 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/infoset/ScalaXMLInfosetOutputter.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/runtime1/infoset/ScalaXMLInfosetOutputter.scala
@@ -19,9 +19,7 @@ package org.apache.daffodil.runtime1.infoset
 
 import scala.collection.mutable.ListBuffer
 import scala.xml.MetaData
-import scala.xml.NamespaceBinding
 import scala.xml.Null
-import scala.xml.PrefixedAttribute
 import scala.xml.UnprefixedAttribute
 
 import org.apache.daffodil.api.DFDLPrimType
@@ -56,16 +54,6 @@ class ScalaXMLInfosetOutputter(showFreedInfo: Boolean = 
false)
     resultNode = Maybe(root(0))
   }
 
-  private def getScope(diElem: DIElement): NamespaceBinding = {
-    val minScope = diElem.metadata.minimizedScope
-    // if including xsi:type is enabled, ensure the xsi namespace is defined 
on the root element
-    if (getIncludeDataType() && stack.length == 1 && minScope.getURI("xsi") == 
null) {
-      NamespaceBinding("xsi", XMLUtils.XSI_NAMESPACE, minScope)
-    } else {
-      minScope
-    }
-  }
-
   private def getAttributes(diElem: DIElement): MetaData = {
     val nilAttr = if (diElem.isNilled) XMLUtils.xmlNilAttribute else Null
     val freedAttr =
@@ -92,14 +80,7 @@ class ScalaXMLInfosetOutputter(showFreedInfo: Boolean = 
false)
       } else {
         nilAttr
       }
-    val typedAttr =
-      if (getIncludeDataType() && diElem.isSimple) {
-        val primName = diElem.erd.optPrimType.get.name
-        new PrefixedAttribute("xsi", "type", "xs:" + primName, freedAttr)
-      } else {
-        freedAttr
-      }
-    typedAttr
+    freedAttr
   }
 
   override def startSimple(se: InfosetSimpleElement): Unit = {
@@ -124,7 +105,7 @@ class ScalaXMLInfosetOutputter(showFreedInfo: Boolean = 
false)
         diSimple.metadata.prefix,
         diSimple.metadata.name,
         attributes,
-        getScope(diSimple),
+        diSimple.metadata.minimizedScope,
         minimizeEmpty = true,
         children*
       )
@@ -149,7 +130,7 @@ class ScalaXMLInfosetOutputter(showFreedInfo: Boolean = 
false)
         diComplex.metadata.prefix,
         diComplex.metadata.name,
         attributes,
-        getScope(diComplex),
+        diComplex.metadata.minimizedScope,
         minimizeEmpty = true,
         children*
       )
diff --git 
a/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLLoader.scala
 
b/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLLoader.scala
index 3cb5caeb3..1471da3a3 100644
--- 
a/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLLoader.scala
+++ 
b/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLLoader.scala
@@ -172,9 +172,19 @@ class TestXMLLoader {
     // and toString will print them out into the text with the <![CDATA[...]]> 
preserved.
     //
     val xmlFromDafLoaderNonNormalized =
-      loader.load(ss, None, addPositionAttributes = false, normalizeCRLFtoLF = 
false)
+      loader.load(
+        ss,
+        None,
+        addPositionAttributes = false,
+        normalizeCRLFtoLF = false
+      )
     val xmlFromDafLoaderNormalized =
-      loader.load(ss, None, addPositionAttributes = false, normalizeCRLFtoLF = 
true)
+      loader.load(
+        ss,
+        None,
+        addPositionAttributes = false,
+        normalizeCRLFtoLF = true
+      )
 
     {
       // compare to the regular scala XML loader
diff --git 
a/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
 
b/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
index 3e70d7129..2c9690f4b 100644
--- 
a/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
+++ 
b/daffodil-core/src/test/scala/org/apache/daffodil/lib/xml/test/unit/TestXMLUtils.scala
@@ -98,6 +98,17 @@ class TestXMLUtils {
     assertEquals("ns2", b)
   }
 
+  @Test def testPrefixNSDiff(): Unit = {
+    // different prefix should error, even though the namespace is the same
+    val d1 = <ns1:a xmlns:ns1="someprefix">a</ns1:a>
+    val d2 = <ns1:a xmlns:ns1="someotherprefix">a</ns1:a>
+    val diffs = XMLUtils.computeDiff(d1, d2, checkPrefixes = true)
+    val Seq((path, a, b)) = diffs
+    assertEquals("/a@prefix-namespace", path)
+    assertEquals("someprefix", a)
+    assertEquals("someotherprefix", b)
+  }
+
   @Test def testNamespaceDiff(): Unit = {
     // different namespace mappings should error
     val d1 = <ns1:a xmlns:ns1="someprefixA">a</ns1:a>
diff --git 
a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala 
b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index 24ea5857b..adf842ce7 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -2805,7 +2805,13 @@ case class DFDLInfoset(di: Node, parent: Infoset) {
     val testSuite = testCase.parent
     val before = testSuite.loadingExceptions.clone()
 
-    val elem = loader.load(infosetSrc, None) // no schema
+    val elem = loader.load(
+      infosetSrc,
+      None,
+      normalizeCRLFtoLF = false,
+      removeComments = false,
+      removeProcInstr = false
+    ) // no schema
     //
     // TODO: DAFFODIL-288 validate the infoset also
     // You can pass the optDataSchema, which appears to be the correct thing
diff --git 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala
 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala
index 696a1ab8e..da0d134a6 100644
--- 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala
+++ 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala
@@ -41,6 +41,7 @@ import org.apache.daffodil.lib.util.MaybeULong
 import org.apache.daffodil.lib.xml.DaffodilSAXParserFactory
 import org.apache.daffodil.lib.xml.XMLUtils
 import org.apache.daffodil.lib.xml.XMLUtils.XMLDifferenceException
+import org.apache.daffodil.processor.tdml
 import org.apache.daffodil.runtime1.iapi.*
 import org.apache.daffodil.runtime1.iapi.DFDL.DaffodilUnhandledSAXException
 import org.apache.daffodil.runtime1.iapi.DFDL.DaffodilUnparseContentHandler
@@ -173,7 +174,7 @@ class DaffodilTDMLDFDLProcessor private[tdml] (
   private def blobPrefix = ""
   private def blobSuffix = ".bin"
 
-  private lazy val tdmlApiInfosetsEnv = 
sys.env.getOrElse("DAFFODIL_TDML_API_INFOSETS", "scala")
+  private lazy val tdmlApiInfosetsEnv = 
sys.env.getOrElse("DAFFODIL_TDML_API_INFOSETS", "xml")
 
   override def withTracing(bool: Boolean): DaffodilTDMLDFDLProcessor = {
     copy(dp = newTracing(bool))
@@ -269,7 +270,7 @@ class DaffodilTDMLDFDLProcessor private[tdml] (
     val outputter = if (tdmlApiInfosetsEnv == "all") {
       TDMLInfosetOutputterAll()
     } else {
-      TDMLInfosetOutputterScala()
+      TDMLInfosetOutputterXML()
     }
     outputter.setBlobAttributes(blobDir, blobPrefix, blobSuffix)
 
@@ -308,7 +309,17 @@ class DaffodilTDMLDFDLProcessor private[tdml] (
           xri.parse(sis)
 
           if (!actual.isError && !errorHandler.isError) {
-            verifySameParseOutput(outputter.xmlStream, saxOutputStream)
+            // we use the scala result because both the ScalaInfosetOutputter 
and
+            // the SAXInfosetOutputter do not implement stringAsXml,
+            // which helps to avoid any differences cause by the stringAsXml 
conversions.
+            val actualOutputArray = outputter
+              .asInstanceOf[tdml.TDMLInfosetOutputterAll]
+              .getScalaResult
+              .toString
+              .getBytes("UTF-8")
+            val baos = new ByteArrayOutputStream(actualOutputArray.length)
+            baos.write(actualOutputArray)
+            verifySameParseOutput(baos, saxOutputStream)
           }
           val dpParseDiag = 
actual.getDiagnostics.asScala.map(_.toString()).toSeq
           val saxParseDiag = 
errorHandler.getDiagnostics.asScala.map(_.toString()).toSeq
@@ -392,7 +403,12 @@ class DaffodilTDMLDFDLProcessor private[tdml] (
       XMLUtils.compareAndReport(
         dpParseXMLNodeOutput,
         saxParseXMLNodeOutput,
-        checkNamespaces = true,
+        // we no longer checkNamespaces because SAX outputs the same 
namespaces as
+        // the XMLTextInfosetOutputter but not the scalaXMLInfosetOutputter, 
so checking
+        // namespaces fails in the DAFFODIL_TDML_API_INFOSETS='all' case due 
to differences
+        // in the scalaXMLInfosetOutputter namespaces, probably having to do 
with
+        // minimizeScope issues
+        // checkNamespaces = true,
         checkPrefixes = true
       )
     } catch {
diff --git 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetInputter.scala
 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetInputter.scala
index 518f38961..e9097b441 100644
--- 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetInputter.scala
+++ 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetInputter.scala
@@ -27,32 +27,37 @@ import org.apache.daffodil.lib.util.Misc
 import org.apache.daffodil.lib.xml.XMLUtils
 import org.apache.daffodil.runtime1.dpath.NodeInfo
 import org.apache.daffodil.runtime1.infoset.JsonInfosetInputter
-import org.apache.daffodil.runtime1.infoset.ScalaXMLInfosetInputter
 import org.apache.daffodil.tdml.TDMLException
 
 class TDMLInfosetInputter(
-  val scalaInputter: ScalaXMLInfosetInputter,
+  val inputter: api.infoset.InfosetInputter,
   others: Seq[api.infoset.InfosetInputter]
 ) extends api.infoset.InfosetInputter {
 
   private def implString: String = "daffodil"
 
   override def getEventType(): InfosetInputterEventType = {
-    val res = scalaInputter.getEventType()
+    val res = inputter.getEventType()
     if (!others.forall(_.getEventType() == res))
-      throw TDMLException("getEventType does not match", Some(implString))
+      throw TDMLException(
+        s"getEventType does not 
match\n${others.zip(others.map(_.getEventType)).mkString("\n")}",
+        Some(implString)
+      )
     res
   }
 
   override def getLocalName(): String = {
-    val res = scalaInputter.getLocalName()
+    val res = inputter.getLocalName()
     if (!others.forall(_.getLocalName() == res))
-      throw TDMLException("getLocalName does not match", Some(implString))
+      throw TDMLException(
+        s"getLocalName does not 
match\n${others.zip(others.map(_.getLocalName)).mkString("\n")}",
+        Some(implString)
+      )
     res
   }
 
   override def getNamespaceURI(): String = {
-    val res = scalaInputter.getNamespaceURI()
+    val res = inputter.getNamespaceURI()
     val resIsEmpty = res == null || res == ""
     val othersMatch = others.forall { i =>
       if (!i.getSupportsNamespaces) {
@@ -66,7 +71,10 @@ class TDMLInfosetInputter(
       }
     }
     if (!othersMatch)
-      throw TDMLException("getNamespaceURI does not match", Some(implString))
+      throw TDMLException(
+        s"getNamespaceURI does not 
match\n${others.filter(_.getSupportsNamespaces).map(o => (o, 
o.getNamespaceURI)).mkString("\n")}",
+        Some(implString)
+      )
     res
   }
 
@@ -74,7 +82,7 @@ class TDMLInfosetInputter(
     primType: NodeInfo.Kind,
     runtimeProperties: java.util.Map[String, String]
   ): String = {
-    val res = scalaInputter.getSimpleText(primType, runtimeProperties)
+    val res = inputter.getSimpleText(primType, runtimeProperties)
     val resIsEmpty = res == null || res == ""
     val otherStrings = others.map { i =>
       // Note in an unparserTestCase, there are no others (infoset inputters), 
because the input infoset is
@@ -100,7 +108,10 @@ class TDMLInfosetInputter(
     }
 
     if (!othersmatch)
-      throw TDMLException("getSimpleText does not match", Some(implString))
+      throw TDMLException(
+        s"getSimpleText does not match for 
$res\n${others.zip(otherStrings).mkString("\n")}",
+        Some(implString)
+      )
 
     if (primType.isInstanceOf[NodeInfo.AnyURI.Kind]) {
       try {
@@ -126,26 +137,32 @@ class TDMLInfosetInputter(
   }
 
   override def isNilled(): JBoolean = {
-    val res = scalaInputter.isNilled()
+    val res = inputter.isNilled()
     if (!others.forall(_.isNilled() == res))
-      throw TDMLException("isNilled does not match", Some(implString))
+      throw TDMLException(
+        s"isNilled does not 
match\n${others.zip(others.map(_.isNilled)).mkString("\n")}",
+        Some(implString)
+      )
     res
   }
 
   override def hasNext(): Boolean = {
-    val res = scalaInputter.hasNext()
+    val res = inputter.hasNext()
     if (!others.forall(_.hasNext() == res))
-      throw TDMLException("hasNext does not match", Some(implString))
+      throw TDMLException(
+        s"hasNext does not 
match\n${others.zip(others.map(_.hasNext)).mkString("\n")}",
+        Some(implString)
+      )
     res
   }
 
   override def next(): Unit = {
-    scalaInputter.next()
+    inputter.next()
     others.foreach(_.next())
   }
 
   override def fini(): Unit = {
-    scalaInputter.fini()
+    inputter.fini()
     others.foreach(_.fini())
   }
 
diff --git 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetOutputter.scala
 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetOutputter.scala
index cf913d687..a04262955 100644
--- 
a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetOutputter.scala
+++ 
b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetOutputter.scala
@@ -19,7 +19,6 @@ package org.apache.daffodil.processor.tdml
 
 import java.io.ByteArrayInputStream
 import java.io.ByteArrayOutputStream
-import java.nio.charset.Charset
 import scala.xml.Node
 
 import org.apache.daffodil.api
@@ -36,29 +35,27 @@ import 
org.apache.daffodil.runtime1.infoset.W3CDOMInfosetOutputter
 import org.apache.daffodil.runtime1.infoset.XMLTextInfosetInputter
 import org.apache.daffodil.runtime1.infoset.XMLTextInfosetOutputter
 
-class TDMLInfosetOutputterScala(scalaOut: ScalaXMLInfosetOutputter)
-  extends TeeInfosetOutputter(Seq(scalaOut)*)
-  with TDMLInfosetOutputter {
+object TDMLInfosetOutputterXML {
+  def apply(): TDMLInfosetOutputterXML = {
+    val baos = new ByteArrayOutputStream()
+    val xmlOut = new XMLTextInfosetOutputter(baos, false)
+    xmlOut.setIncludeDataType(true)
+    new TDMLInfosetOutputterXML(baos, xmlOut)
+  }
+}
 
-  override def getResult: Node = scalaOut.getResult()
+class TDMLInfosetOutputterXML(
+  override val xmlStream: ByteArrayOutputStream,
+  xmlOut: XMLTextInfosetOutputter
+) extends TeeInfosetOutputter(Seq(xmlOut)*)
+  with TDMLInfosetOutputter {
 
-  override lazy val xmlStream: ByteArrayOutputStream = {
-    val bos = new ByteArrayOutputStream()
-    bos.write(getResult.toString().getBytes(Charset.defaultCharset()))
-    bos
-  }
+  override def getResult: Node =
+    scala.xml.XML.load(new ByteArrayInputStream(xmlStream.toByteArray))
 
   override def toInfosetInputter: TDMLInfosetInputter = {
-    val scalaIn = new ScalaXMLInfosetInputter(scalaOut.getResult())
-    new TDMLInfosetInputter(scalaIn, Seq())
-  }
-}
-
-object TDMLInfosetOutputterScala {
-  def apply(): TDMLInfosetOutputterScala = {
-    val scalaOut = new ScalaXMLInfosetOutputter()
-    scalaOut.setIncludeDataType(true)
-    new TDMLInfosetOutputterScala(scalaOut)
+    val xmlIn = new XMLTextInfosetInputter(new 
ByteArrayInputStream(xmlStream.toByteArray))
+    new TDMLInfosetInputter(xmlIn, Seq())
   }
 }
 
@@ -73,7 +70,9 @@ class TDMLInfosetOutputterAll(
 ) extends TeeInfosetOutputter(Seq(xmlOut, scalaOut, jdomOut, w3cdomOut, 
jsonOut)*)
   with TDMLInfosetOutputter {
 
-  override def getResult: Node = scalaOut.getResult()
+  def getScalaResult: Node = scalaOut.getResult()
+  override def getResult: Node =
+    scala.xml.XML.load(new ByteArrayInputStream(xmlStream.toByteArray))
 
   override def toInfosetInputter: TDMLInfosetInputter = {
     val scalaIn = new ScalaXMLInfosetInputter(scalaOut.getResult())
@@ -82,10 +81,14 @@ class TDMLInfosetOutputterAll(
     val jsonIn = new JsonInfosetInputter(new 
ByteArrayInputStream(jsonStream.toByteArray))
     val xmlIn = new XMLTextInfosetInputter(new 
ByteArrayInputStream(xmlStream.toByteArray))
     val nullIn = {
-      val events = NullInfosetInputter.toEvents(new 
ByteArrayInputStream(xmlStream.toByteArray))
+      val events = NullInfosetInputter.toEvents(
+        new ByteArrayInputStream(
+          scalaOut.getResult().toString().getBytes("UTF-8")
+        )
+      )
       new NullInfosetInputter(events)
     }
-    new TDMLInfosetInputter(scalaIn, Seq(jdomIn, w3cdomIn, jsonIn, xmlIn, 
nullIn))
+    new TDMLInfosetInputter(xmlIn, Seq(jdomIn, w3cdomIn, jsonIn, scalaIn, 
nullIn))
   }
 }
 
@@ -100,7 +103,7 @@ object TDMLInfosetOutputterAll {
     val jsonOut = new JsonInfosetOutputter(jsonStream, false)
     val xmlOut = new XMLTextInfosetOutputter(xmlStream, false)
 
-    Seq(scalaOut, jdomOut, w3cdomOut, jsonOut, xmlOut).foreach { out =>
+    Seq(jdomOut, w3cdomOut, jsonOut, xmlOut).foreach { out =>
       out.setIncludeDataType(true)
     }
 
diff --git 
a/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLITdml.scala
 
b/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLITdml.scala
index 1f0e062f3..046fbe6fb 100644
--- 
a/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLITdml.scala
+++ 
b/daffodil-test-integration/src/test/scala/org/apache/daffodil/cliTest/TestCLITdml.scala
@@ -45,7 +45,7 @@ class TestCLITdml {
       
"daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/Entities.tdml"
     )
 
-    val envs = Map("DAFFODIL_TDML_API_INFOSETS" -> "scala")
+    val envs = Map("DAFFODIL_TDML_API_INFOSETS" -> "xml")
 
     runCLI(args"test -i -t $tdml byte_entities_6_08", envs = envs) { cli =>
       // parse
diff --git 
a/daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.api.validation.ValidatorFactory
 
b/daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.api.validation.ValidatorFactory
new file mode 100644
index 000000000..a12f49a78
--- /dev/null
+++ 
b/daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.api.validation.ValidatorFactory
@@ -0,0 +1,16 @@
+#  Licensed to the Apache Software Foundation (ASF) under one or more
+#  contributor license agreements.  See the NOTICE file distributed with
+#  this work for additional information regarding copyright ownership.
+#  The ASF licenses this file to You under the Apache License, Version 2.0
+#  (the "License"); you may not use this file except in compliance with
+#  the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+org.apache.daffodil.infoset.TestStringAsXmlValidatorFactory
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXML.tdml 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXML.tdml
new file mode 100644
index 000000000..9e88bc312
--- /dev/null
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXML.tdml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<testSuite suiteName="StringAsXML" description="StringAsXML TDML tests"
+                xmlns="http://www.ibm.com/xmlns/dfdl/testData";
+                xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData";
+                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+                xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/";
+                xmlns:xs="http://www.w3.org/2001/XMLSchema";
+                xmlns:ex="http://example.com";
+                defaultValidation="on">
+
+  <parserTestCase name="stringAsXml_01_a" root="binMessage"
+                       
model="/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd"
+                       validation="TestStringAsXmlValidator">
+    <document>
+      <documentPart 
type="file">stringAsXml/namespaced/binMessage_01.dat</documentPart>
+    </document>
+    <infoset>
+      <dfdlInfoset 
type="file">stringAsXml/namespaced/binMessage_01.dat.xml</dfdlInfoset>
+    </infoset>
+  </parserTestCase>
+  
+  <parserTestCase name="stringAsXml_01_b" root="binMessage"
+                       
model="/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd">
+    <document>
+      <documentPart 
type="file">stringAsXml/namespaced/binMessage_01.dat</documentPart>
+    </document>
+    <infoset>
+      <dfdlInfoset 
type="file">stringAsXml/namespaced/binMessage_01.dat.xml</dfdlInfoset>
+    </infoset>
+    <validationErrors>
+      <error>Element 'xmlStr' is a simple type</error>
+    </validationErrors>
+  </parserTestCase>
+
+  <parserTestCase name="stringAsXml_04" root="binMessage"
+                  
model="/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd">
+    <document>
+      <documentPart 
type="file">stringAsXml/namespaced/binMessage_03.dat</documentPart>
+    </document>
+    <errors>
+      <error>Unexpected character</error>
+    </errors>
+  </parserTestCase>
+
+  <parserTestCase name="stringAsXml_09" root="binMessage"
+                  
model="/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd">
+    <document>
+      <documentPart 
type="file">stringAsXml/namespaced/binMessage_08.dat</documentPart>
+    </document>
+    <errors>
+      <error>Undeclared general entity "name"</error>
+    </errors>
+  </parserTestCase>
+
+
+  <parserTestCase name="stringAsXml_10" root="binMessage"
+                  
model="/org/apache/daffodil/infoset/stringAsXml/nonamespace/xsd/binMessage.dfdl.xsd"
+                  validation="TestStringAsXmlValidator">
+    <document>
+      <documentPart 
type="file">stringAsXml/nonamespace/binMessage_01.dat</documentPart>
+    </document>
+    <infoset>
+      <dfdlInfoset 
type="file">stringAsXml/nonamespace/binMessage_01.dat.xml</dfdlInfoset>
+    </infoset>
+    <validationErrors>
+      <error>Value '=invalid field' is not facet-valid</error>
+    </validationErrors>
+  </parserTestCase>
+
+  <parserTestCase name="stringAsXml_11" root="binMessageA"
+                  
model="/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd"
+                  validation="TestStringAsXmlValidator">
+    <document>
+      <documentPart 
type="file">stringAsXml/namespaced/binMessage_01a.dat</documentPart>
+    </document>
+    <infoset>
+      <dfdlInfoset 
type="file">stringAsXml/namespaced/binMessage_01a.dat.xml</dfdlInfoset>
+    </infoset>
+
+  </parserTestCase>
+</testSuite>
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat
index bdb4f0b65..c5b104518 100644
Binary files 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat
 and 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat
 differ
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
index c54b830fc..669b02095 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
@@ -5,7 +5,7 @@
     <xmlStr>
       <stringAsXml xmlns="">
 <p:root xmlns:q="urn:payload" xmlns:p="urn:payload" attr2="4" attr1=" value ">
-  <!-- commment -->
+  <!-- contains CRLFs and LFs -->
   <?processing instruction?>
   <field><![CDATA[Field ]]> with <![CDATA[cdata]]> </field> here is mixed 
content
   <field>spaces</field>    <field>   spaces   </field> and more mixed content
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat
index 92703251f..c5b104518 100644
Binary files 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat
 and 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat
 differ
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat
similarity index 72%
copy from 
daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat
copy to 
daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat
index 92703251f..9ea0e13f4 100644
Binary files 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat
 and 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat
 differ
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat.xml
similarity index 75%
copy from 
daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
copy to 
daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat.xml
index c54b830fc..875d7f4ce 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat.xml
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<b:binMessage xmlns:b="urn:bin">
+<b:binMessageA xmlns:b="urn:bin">
   <record>
     <id>1</id>
     <xmlStr>
       <stringAsXml xmlns="">
 <p:root xmlns:q="urn:payload" xmlns:p="urn:payload" attr2="4" attr1=" value ">
-  <!-- commment -->
+  <!-- contains CRLFs and LFs -->
   <?processing instruction?>
   <field><![CDATA[Field ]]> with <![CDATA[cdata]]> </field> here is mixed 
content
   <field>spaces</field>    <field>   spaces   </field> and more mixed content
@@ -28,11 +28,14 @@
     <id>2</id>
     <xmlStr>
       <stringAsXml xmlns="">
-<r:root xmlns:r="urn:payload">
-  <field>second record</field>
-</r:root>
+        <r:root xmlns:r="urn:payload">
+          <foo  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:type="xs:int">
+            <!-- inline comment -->
+            5
+          </foo>
+        </r:root>
       </stringAsXml>
     </xmlStr>
     <priority>1</priority>
   </record>
-</b:binMessage>
+</b:binMessageA>
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd
index a7d456c16..1f27c8dcd 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessage.dfdl.xsd
@@ -72,5 +72,31 @@
       </sequence>
     </complexType>
   </element>
-  
+
+  <element name="binMessageA" dfdl:terminator="%#r00;%#r0A;">
+    <complexType>
+      <sequence>
+        <element name="record" maxOccurs="unbounded">
+          <complexType>
+            <sequence dfdl:separator="%NL;" dfdl:separatorPosition="postfix">
+              <element name="id" type="xs:int" />
+              <sequence dfdl:hiddenGroupRef="b:strLenHG" />
+              <element name="xmlStr"
+                       dfdl:lengthKind="explicit" dfdl:length="{ ../strLen }"
+                       dfdlx:runtimeProperties="stringAsXml=true">
+                <simpleType>
+                  <restriction base="xs:string">
+                    <maxLength value="0" />
+                  </restriction>
+                </simpleType>
+              </element>
+              <element name="priority" type="xs:int" />
+            </sequence>
+          </complexType>
+        </element>
+      </sequence>
+    </complexType>
+  </element>
+
+
 </schema>
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessageWithXmlPayload.xsd
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessageWithXmlPayload.xsd
index 3b46c663c..3118b0628 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessageWithXmlPayload.xsd
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/binMessageWithXmlPayload.xsd
@@ -50,6 +50,33 @@
       </sequence>
     </complexType>
   </element>
+
+  <element name="binMessageA">
+    <complexType>
+      <sequence>
+        <element name="record" maxOccurs="unbounded">
+          <complexType>
+            <sequence>
+              <element name="id" type="xs:int" />
+              <!--
+              The XMLTextInfosetOutputter converts this xmlStr element, which 
used to be a
+              simple element with xs:string type, to a complex element. This 
complex element
+              contains a "wrapper" element defined in the 
stringAsXmlWrapper.xsd schema file,
+              which references the schema that defines the payload XML. See the
+              stringAsXMLWrapper.xsd file for more information.
+              -->
+              <element name="xmlStr">
+                <complexType>
+                  <group xmlns:s="urn:stringAsXml" ref="s:stringAsXmlGroupA" />
+                </complexType>
+              </element>
+              <element name="priority" type="xs:int" />
+            </sequence>
+          </complexType>
+        </element>
+      </sequence>
+    </complexType>
+  </element>
   
 </schema>
 
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/stringAsXmlWrapper.xsd
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/stringAsXmlWrapper.xsd
index 3c7cd0bff..87ad24db7 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/stringAsXmlWrapper.xsd
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/stringAsXmlWrapper.xsd
@@ -77,6 +77,18 @@ validate XML embedded in data and subsequently embedded into 
the infoset.
       </element>
     </sequence>
   </group>
+
+  <group name="stringAsXmlGroupA">
+    <sequence>
+      <element name="stringAsXml">
+        <complexType>
+          <sequence>
+            <element xmlns:p="urn:payload" ref="p:rootA" />
+          </sequence>
+        </complexType>
+      </element>
+    </sequence>
+  </group>
   
 </schema>
 
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/xmlPayload.xsd
 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/xmlPayload.xsd
index 2f92d344c..870d89b89 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/xmlPayload.xsd
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/xsd/xmlPayload.xsd
@@ -42,5 +42,13 @@
       <attribute name="attr2" type="xs:int" />
     </complexType>
   </element>
+
+  <element name="rootA">
+    <complexType mixed="true">
+      <sequence>
+        <element name="foo" type="xs:int"/>
+      </sequence>
+    </complexType>
+  </element>
   
 </schema>
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables_01.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables_01.tdml
index 6d636c6af..545f47029 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables_01.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section07/variables/variables_01.tdml
@@ -48,7 +48,7 @@
     <tdml:infoset>
       <tdml:dfdlInfoset>
         <ex:c_2>
-          <d xsi:type="xsd:int">42</d>
+          <d xsi:type="xsd:string">42</d>
         </ex:c_2>
       </tdml:dfdlInfoset>
     </tdml:infoset>
diff --git 
a/daffodil-test/src/test/scala/org/apache/daffodil/infoset/TestStringAsXmlTDML.scala
 
b/daffodil-test/src/test/scala/org/apache/daffodil/infoset/TestStringAsXmlTDML.scala
new file mode 100644
index 000000000..0495d584c
--- /dev/null
+++ 
b/daffodil-test/src/test/scala/org/apache/daffodil/infoset/TestStringAsXmlTDML.scala
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.infoset
+
+import org.apache.daffodil.junit.tdml.TdmlSuite
+import org.apache.daffodil.junit.tdml.TdmlTests
+
+import org.junit.Test
+
+object TestStringAsXmlTDML extends TdmlSuite {
+  val tdmlResource = "/org/apache/daffodil/infoset/stringAsXML.tdml"
+}
+
+class TestStringAsXmlTDML extends TdmlTests {
+  val tdmlSuite = TestStringAsXmlTDML
+
+  @Test def stringAsXml_01_a = test
+  @Test def stringAsXml_01_b = test
+  @Test def stringAsXml_04 = test
+  @Test def stringAsXml_09 = test
+  @Test def stringAsXml_10 = test
+  @Test def stringAsXml_11 = test
+}
diff --git 
a/daffodil-test/src/test/scala/org/apache/daffodil/infoset/TestStringAsXmlValidator.scala
 
b/daffodil-test/src/test/scala/org/apache/daffodil/infoset/TestStringAsXmlValidator.scala
new file mode 100644
index 000000000..560329ad8
--- /dev/null
+++ 
b/daffodil-test/src/test/scala/org/apache/daffodil/infoset/TestStringAsXmlValidator.scala
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.daffodil.infoset
+
+import java.io.InputStream
+import java.net.URL
+import java.util.Properties
+
+import org.apache.daffodil.api.validation.ValidationHandler
+import org.apache.daffodil.api.validation.Validator
+import org.apache.daffodil.api.validation.ValidatorFactory
+import org.apache.daffodil.validation.XercesValidator
+
+object TestStringAsXmlValidator {
+  val name = "TestStringAsXmlValidator"
+}
+
+class TestStringAsXmlValidator(schemaURL: String) extends Validator {
+  private lazy val xercesValidator = XercesValidator.fromURL(new 
URL(schemaURL))
+
+  override def validateXML(document: InputStream, vh: ValidationHandler): Unit 
= {
+    xercesValidator.validateXML(document, vh)
+  }
+}
+
+class TestStringAsXmlValidatorFactory extends ValidatorFactory {
+
+  override def name: String = TestStringAsXmlValidator.name
+
+  override def make(config: Properties) = {
+    val dfdlSchema = config.getProperty(name)
+    // assumes the validation XSD path is in the same as the DFDL schema but 
with a different suffix
+    val xsdSchema = dfdlSchema.replace(".dfdl.xsd", "WithXmlPayload.xsd")
+    new TestStringAsXmlValidator(xsdSchema)
+  }
+}
diff --git a/project/Rat.scala b/project/Rat.scala
index 825a66152..e39a69574 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -123,9 +123,15 @@ object Rat {
     file(
       
"daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat"
     ),
+    file(
+      
"daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat"
+    ),
     file(
       
"daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml"
     ),
+    file(
+      
"daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01a.dat.xml"
+    ),
     file(
       
"daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat"
     ),

Reply via email to