Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions source/MaterialXFormat/External/PugiXML/pugixml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3927,7 +3927,7 @@ PUGI__NS_BEGIN
xml_encoding encoding;
};

PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type)
PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags)
{
while (*s)
{
Expand All @@ -3947,12 +3947,18 @@ PUGI__NS_BEGIN
break;
case '<':
// MaterialX: Allow angle brackets in MTLX serialization.
writer.write(*s);
if (flags & format_mtlx)
writer.write('<');
else
writer.write('&', 'l', 't', ';');
Comment thread
kwokcb marked this conversation as resolved.
Outdated
++s;
break;
case '>':
// MaterialX: Allow angle brackets in MTLX serialization.
writer.write(*s);
// MaterialX: Allow angle brackets in MTLX serialization.
if (flags & format_mtlx)
writer.write('>');
else
writer.write('&', 'g', 't', ';');
Comment thread
kwokcb marked this conversation as resolved.
Outdated
++s;
break;
case '"':
Expand All @@ -3975,7 +3981,7 @@ PUGI__NS_BEGIN
if (flags & format_no_escapes)
writer.write_string(s);
else
text_output_escaped(writer, s, type);
text_output_escaped(writer, s, type, flags);
}

PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s)
Expand Down
3 changes: 3 additions & 0 deletions source/MaterialXFormat/External/PugiXML/pugixml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ namespace pugi
// Don't output empty element tags, instead writing an explicit start and end tag even if there are no children. This flag is off by default.
const unsigned int format_no_empty_element_tags = 0x80;

// MaterialX: This flag determines if MaterialX custom output formatting is enabled. THis flag is on by default
const unsigned int format_mtlx = 0x100;

// The default set of formatting flags.
// Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none.
const unsigned int format_default = format_indent;
Expand Down
11 changes: 10 additions & 1 deletion source/MaterialXFormat/XmlIo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,19 @@ void readFromXmlString(DocumentPtr doc, const string& str, const FileSearchPath&

void writeToXmlStream(DocumentPtr doc, std::ostream& stream, const XmlWriteOptions* writeOptions)
{
// Check for XML strictness
unsigned int flags = format_default;
bool strictXML = writeOptions ? writeOptions->strictXML : false;
if (!strictXML)
{
// If not strict add MaterialX specific output formatting.
flags |= format_mtlx;
}

xml_document xmlDoc;
xml_node xmlRoot = xmlDoc.append_child("materialx");
documentToXml(doc, xmlRoot, writeOptions);
xmlDoc.save(stream, " ");
xmlDoc.save(stream, " ", flags);
Comment thread
kwokcb marked this conversation as resolved.
Outdated
}

void writeToXmlFile(DocumentPtr doc, const FilePath& filename, const XmlWriteOptions* writeOptions)
Expand Down
5 changes: 5 additions & 0 deletions source/MaterialXFormat/XmlIo.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ class MX_FORMAT_API XmlWriteOptions
/// XIncludes rather than explicit data. Defaults to true.
bool writeXIncludeEnable;

/// If true output will follow a strict interpretation of the XML specification.
/// If false, then MaterialX customizations which deviate from the XML specification will be allowed.
// Defaults to false.
bool strictXML = false;

/// If provided, this function will be used to exclude specific elements
/// (those returning false) from the write operation. Defaults to nullptr.
ElementPredicate elementPredicate;
Expand Down
41 changes: 41 additions & 0 deletions source/MaterialXTest/MaterialXFormat/XmlIo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,3 +371,44 @@ TEST_CASE("Locale region testing", "[xmlio]")
// Restore the original locale.
std::locale::global(origLocale);
}

TEST_CASE("XML strictness", "[xmlio2]")
{
mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath();
mx::DocumentPtr stdlib = mx::createDocument();
mx::loadLibraries({ "libraries" }, searchPath, stdlib);

mx::DocumentPtr doc = mx::createDocument();
doc->setDataLibrary(stdlib);

// Create image node with illegal <> characters
mx::NodePtr imageNode = doc->addNode("image", "testImage");
imageNode->addInputsFromNodeDef();
mx::InputPtr fileInput = imageNode->getInput("file");
fileInput->setValue("<>");

// Write to string with default options
mx::XmlWriteOptions writeOptions;
std::string output_string = mx::writeToXmlString(doc, &writeOptions);
// Make sure there are no escaped characters
REQUIRE(output_string.find("&lt;&gt;") == std::string::npos);

// Write with escaped characters enabled
writeOptions.strictXML = true;
output_string = mx::writeToXmlString(doc, &writeOptions);
// Look for escaped characters
REQUIRE(output_string.find("&lt;&gt;") != std::string::npos);

// Read in the document with the escaped characters and verify that the value
// is unescaped properly
mx::DocumentPtr readDoc = mx::createDocument();
readDoc->setDataLibrary(stdlib);
mx::readFromXmlString(readDoc , output_string);
imageNode = readDoc->getNode("testImage");
REQUIRE(imageNode != nullptr);
fileInput = imageNode->getInput("file");
REQUIRE(fileInput != nullptr);
std::string unescaped_string = fileInput->getValueString();
// There should not be any escaped characters in the value string
REQUIRE(unescaped_string.find("&lt;&gt;") == std::string::npos);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was always the logic as read always unescapes.

}
Loading