Переглянути джерело

Merge pull request #1021 from Malcohol/Malcohol/optionalAposHandling

Optional Apos escaping
Lee Thomason 8 місяців тому
батько
коміт
30dee1efa0
3 змінених файлів з 47 додано та 5 видалено
  1. 6 4
      tinyxml2.cpp
  2. 6 1
      tinyxml2.h
  3. 35 0
      xmltest.cpp

+ 6 - 4
tinyxml2.cpp

@@ -2577,7 +2577,7 @@ void XMLDocument::PopDepth()
 	--_parsingDepth;
 }
 
-XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
+XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth, EscapeAposCharsInAttributes aposInAttributes ) :
     _elementJustOpened( false ),
     _stack(),
     _firstElement( true ),
@@ -2594,9 +2594,11 @@ XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
     }
     for( int i=0; i<NUM_ENTITIES; ++i ) {
         const char entityValue = entities[i].value;
-        const unsigned char flagIndex = static_cast<unsigned char>(entityValue);
-        TIXMLASSERT( flagIndex < ENTITY_RANGE );
-        _entityFlag[flagIndex] = true;
+        if ((aposInAttributes == ESCAPE_APOS_CHARS_IN_ATTRIBUTES) || (entityValue != SINGLE_QUOTE)) {
+            const unsigned char flagIndex = static_cast<unsigned char>(entityValue);
+            TIXMLASSERT( flagIndex < ENTITY_RANGE );
+            _entityFlag[flagIndex] = true;
+        }
     }
     _restrictedEntityFlag[static_cast<unsigned char>('&')] = true;
     _restrictedEntityFlag[static_cast<unsigned char>('<')] = true;

+ 6 - 1
tinyxml2.h

@@ -2239,13 +2239,18 @@ private:
 class TINYXML2_LIB XMLPrinter : public XMLVisitor
 {
 public:
+    enum EscapeAposCharsInAttributes {
+        ESCAPE_APOS_CHARS_IN_ATTRIBUTES,
+        DONT_ESCAPE_APOS_CHARS_IN_ATTRIBUTES
+    };
+
     /** Construct the printer. If the FILE* is specified,
     	this will print to the FILE. Else it will print
     	to memory, and the result is available in CStr().
     	If 'compact' is set to true, then output is created
     	with only required whitespace and newlines.
     */
-    XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
+    XMLPrinter( FILE* file=0, bool compact = false, int depth = 0, EscapeAposCharsInAttributes aposInAttributes = ESCAPE_APOS_CHARS_IN_ATTRIBUTES );
     virtual ~XMLPrinter()	{}
 
     /** If streaming, write the BOM and declaration. */

+ 35 - 0
xmltest.cpp

@@ -2695,6 +2695,41 @@ int main( int argc, const char ** argv )
 		XMLTest("Test attribute encode with a Hex value", value5, "!"); // hex value in unicode value
 	}
 
+	// ---------- XMLPrinter Apos Escaping ------
+	{
+		const char* testText = "text containing a ' character";
+		XMLDocument doc;
+		XMLElement* element = doc.NewElement( "element" );
+		doc.InsertEndChild( element );
+		element->SetAttribute( "attrib", testText );
+		{
+			XMLPrinter defaultPrinter;
+			doc.Print( &defaultPrinter );
+			const char* defaultOutput = defaultPrinter.CStr();
+			const bool foundTextWithUnescapedApos = (strstr(defaultOutput, testText) != nullptr); 
+			XMLTest("Default XMLPrinter should escape ' characters", false, foundTextWithUnescapedApos);
+			{
+				XMLDocument parsingDoc;
+				parsingDoc.Parse(defaultOutput);
+				const XMLAttribute* attrib = parsingDoc.FirstChildElement("element")->FindAttribute("attrib");
+				XMLTest("Default XMLPrinter should output parsable xml", testText, attrib->Value(), true);
+			}
+		}
+		{
+			XMLPrinter customPrinter(0, false, 0, XMLPrinter::DONT_ESCAPE_APOS_CHARS_IN_ATTRIBUTES);
+			doc.Print( &customPrinter );
+			const char* customOutput = customPrinter.CStr();
+			const bool foundTextWithUnescapedApos = (strstr(customOutput, testText) != nullptr); 
+			XMLTest("Custom XMLPrinter should not escape ' characters", true, foundTextWithUnescapedApos);
+			{
+				XMLDocument parsingDoc;
+				parsingDoc.Parse(customOutput);
+				const XMLAttribute* attrib = parsingDoc.FirstChildElement("element")->FindAttribute("attrib");
+				XMLTest("Custom XMLPrinter should output parsable xml", testText, attrib->Value(), true);
+			}
+		}
+	}
+	
     // ----------- Performance tracking --------------
 	{
 #if defined( _MSC_VER )