CPackWIX: Handle text nodes in XML patch content

This commit is contained in:
Nils Gladitz 2015-10-12 21:53:08 +02:00
parent e5fb30fb5b
commit 5a266095ee
6 changed files with 119 additions and 20 deletions

View File

@ -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<const cmWIXPatchElement&>(*node), writer);
break;
case cmWIXPatchNode::TEXT:
writer.AddTextNode(dynamic_cast<const cmWIXPatchText&>(*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;

View File

@ -33,6 +33,9 @@ public:
bool CheckForUnappliedFragments();
private:
void ApplyElementChildren(const cmWIXPatchElement& element,
cmWIXSourceWriter& writer);
void ApplyElement(const cmWIXPatchElement& element,
cmWIXSourceWriter& writer);

View File

@ -16,6 +16,21 @@
#include <cm_expat.h>
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,

View File

@ -20,11 +20,33 @@
#include <map>
#include <list>
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<cmWIXPatchElement*> child_list_t;
typedef std::list<cmWIXPatchNode*> child_list_t;
typedef std::map<std::string, std::string> 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);

View File

@ -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)
{

View File

@ -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);