From 5a266095ee778fb700c067c55ff0b59777a72c50 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Mon, 12 Oct 2015 21:53:08 +0200 Subject: [PATCH] CPackWIX: Handle text nodes in XML patch content --- Source/CPack/WiX/cmWIXPatch.cxx | 34 +++++++++++------ Source/CPack/WiX/cmWIXPatch.h | 3 ++ Source/CPack/WiX/cmWIXPatchParser.cxx | 52 ++++++++++++++++++++++---- Source/CPack/WiX/cmWIXPatchParser.h | 29 +++++++++++++- Source/CPack/WiX/cmWIXSourceWriter.cxx | 19 ++++++++++ Source/CPack/WiX/cmWIXSourceWriter.h | 2 + 6 files changed, 119 insertions(+), 20 deletions(-) diff --git a/Source/CPack/WiX/cmWIXPatch.cxx b/Source/CPack/WiX/cmWIXPatch.cxx index 5a8dc6351..471c3a411 100644 --- a/Source/CPack/WiX/cmWIXPatch.cxx +++ b/Source/CPack/WiX/cmWIXPatch.cxx @@ -33,15 +33,32 @@ void cmWIXPatch::ApplyFragment( if(i == Fragments.end()) return; const cmWIXPatchElement& fragment = i->second; - for(cmWIXPatchElement::child_list_t::const_iterator - j = fragment.children.begin(); j != fragment.children.end(); ++j) - { - ApplyElement(**j, writer); - } + + this->ApplyElementChildren(fragment, writer); Fragments.erase(i); } +void cmWIXPatch::ApplyElementChildren( + const cmWIXPatchElement& element, cmWIXSourceWriter& writer) +{ + for(cmWIXPatchElement::child_list_t::const_iterator + j = element.children.begin(); j != element.children.end(); ++j) + { + cmWIXPatchNode *node = *j; + + switch(node->type()) + { + case cmWIXPatchNode::ELEMENT: + ApplyElement(dynamic_cast(*node), writer); + break; + case cmWIXPatchNode::TEXT: + writer.AddTextNode(dynamic_cast(*node).text); + break; + } + } +} + void cmWIXPatch::ApplyElement( const cmWIXPatchElement& element, cmWIXSourceWriter& writer) { @@ -53,16 +70,11 @@ void cmWIXPatch::ApplyElement( writer.AddAttribute(i->first, i->second); } - for(cmWIXPatchElement::child_list_t::const_iterator - i = element.children.begin(); i != element.children.end(); ++i) - { - ApplyElement(**i, writer); - } + this->ApplyElementChildren(element, writer); writer.EndElement(element.name); } - bool cmWIXPatch::CheckForUnappliedFragments() { std::string fragmentList; diff --git a/Source/CPack/WiX/cmWIXPatch.h b/Source/CPack/WiX/cmWIXPatch.h index 7b7b2f170..d53fcb47f 100644 --- a/Source/CPack/WiX/cmWIXPatch.h +++ b/Source/CPack/WiX/cmWIXPatch.h @@ -33,6 +33,9 @@ public: bool CheckForUnappliedFragments(); private: + void ApplyElementChildren(const cmWIXPatchElement& element, + cmWIXSourceWriter& writer); + void ApplyElement(const cmWIXPatchElement& element, cmWIXSourceWriter& writer); diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx index e066c280f..14c5413bc 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.cxx +++ b/Source/CPack/WiX/cmWIXPatchParser.cxx @@ -16,6 +16,21 @@ #include +cmWIXPatchNode::Type cmWIXPatchText::type() +{ + return cmWIXPatchNode::TEXT; +} + +cmWIXPatchNode::Type cmWIXPatchElement::type() +{ + return cmWIXPatchNode::ELEMENT; +} + +cmWIXPatchNode::~cmWIXPatchNode() +{ + +} + cmWIXPatchElement::~cmWIXPatchElement() { for(child_list_t::iterator i = children.begin(); i != children.end(); ++i) @@ -63,20 +78,20 @@ void cmWIXPatchParser::StartElement(const std::string& name, const char **atts) { cmWIXPatchElement &parent = *ElementStack.back(); - parent.children.resize(parent.children.size() + 1); - cmWIXPatchElement*& currentElement = parent.children.back(); - currentElement = new cmWIXPatchElement; - currentElement->name = name; + cmWIXPatchElement *element = new cmWIXPatchElement; + parent.children.push_back(element); + + element->name = name; for(size_t i = 0; atts[i]; i += 2) { std::string key = atts[i]; std::string value = atts[i+1]; - currentElement->attributes[key] = value; + element->attributes[key] = value; } - ElementStack.push_back(currentElement); + ElementStack.push_back(element); } } @@ -117,11 +132,34 @@ void cmWIXPatchParser::EndElement(const std::string& name) } else { - ElementStack.pop_back(); + ElementStack.pop_back(); } } } +void cmWIXPatchParser::CharacterDataHandler(const char* data, int length) +{ + const char* whitespace = "\x20\x09\x0d\x0a"; + + if(State == INSIDE_FRAGMENT) + { + cmWIXPatchElement &parent = *ElementStack.back(); + + std::string text(data, length); + + std::string::size_type first = text.find_first_not_of(whitespace); + std::string::size_type last = text.find_last_not_of(whitespace); + + if(first != std::string::npos && last != std::string::npos) + { + cmWIXPatchText *text_node = new cmWIXPatchText; + text_node->text = text.substr(first, last - first + 1); + + parent.children.push_back(text_node); + } + } +} + void cmWIXPatchParser::ReportError(int line, int column, const char* msg) { cmCPackLogger(cmCPackLog::LOG_ERROR, diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h index acfb4c071..acaeae364 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.h +++ b/Source/CPack/WiX/cmWIXPatchParser.h @@ -20,11 +20,33 @@ #include #include -struct cmWIXPatchElement +struct cmWIXPatchNode { + enum Type + { + TEXT, + ELEMENT + }; + + virtual ~cmWIXPatchNode(); + + virtual Type type() = 0; +}; + +struct cmWIXPatchText : public cmWIXPatchNode +{ + virtual Type type(); + + std::string text; +}; + +struct cmWIXPatchElement : cmWIXPatchNode +{ + virtual Type type(); + ~cmWIXPatchElement(); - typedef std::list child_list_t; + typedef std::list child_list_t; typedef std::map attributes_t; std::string name; @@ -48,6 +70,9 @@ private: void StartFragment(const char **attributes); virtual void EndElement(const std::string& name); + + virtual void CharacterDataHandler(const char* data, int length); + virtual void ReportError(int line, int column, const char* msg); void ReportValidationError(std::string const& message); diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx index 8d38e9b58..63acb278f 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.cxx +++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx @@ -102,6 +102,25 @@ void cmWIXSourceWriter::EndElement(std::string const& name) State = DEFAULT; } +void cmWIXSourceWriter::AddTextNode(std::string const& text) +{ + if(State == BEGIN) + { + File << ">"; + } + + if(Elements.empty()) + { + cmCPackLogger(cmCPackLog::LOG_ERROR, + "can not add text without open WiX element in '" << + SourceFilename << "'" << std::endl); + return; + } + + File << this->EscapeAttributeValue(text); + State = DEFAULT; +} + void cmWIXSourceWriter::AddProcessingInstruction( std::string const& target, std::string const& content) { diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h index 3b9999cc6..9e303f0d8 100644 --- a/Source/CPack/WiX/cmWIXSourceWriter.h +++ b/Source/CPack/WiX/cmWIXSourceWriter.h @@ -34,6 +34,8 @@ public: void EndElement(std::string const& name); + void AddTextNode(std::string const& text); + void AddProcessingInstruction( std::string const& target, std::string const& content);