浏览代码

Merge topic 'wix-text-node'

5a266095 CPackWIX: Handle text nodes in XML patch content
Brad King 10 年之前
父节点
当前提交
088fcbf733

+ 22 - 10
Source/CPack/WiX/cmWIXPatch.cxx

@@ -33,13 +33,30 @@ void cmWIXPatch::ApplyFragment(
   if(i == Fragments.end()) return;
 
   const cmWIXPatchElement& fragment = i->second;
+
+  this->ApplyElementChildren(fragment, writer);
+
+  Fragments.erase(i);
+}
+
+void cmWIXPatch::ApplyElementChildren(
+  const cmWIXPatchElement& element, cmWIXSourceWriter& writer)
+{
   for(cmWIXPatchElement::child_list_t::const_iterator
-    j = fragment.children.begin(); j != fragment.children.end(); ++j)
+    j = element.children.begin(); j != element.children.end(); ++j)
+  {
+  cmWIXPatchNode *node = *j;
+
+  switch(node->type())
     {
-    ApplyElement(**j, writer);
+    case cmWIXPatchNode::ELEMENT:
+      ApplyElement(dynamic_cast<const cmWIXPatchElement&>(*node), writer);
+      break;
+    case cmWIXPatchNode::TEXT:
+      writer.AddTextNode(dynamic_cast<const cmWIXPatchText&>(*node).text);
+      break;
     }
-
-  Fragments.erase(i);
+  }
 }
 
 void cmWIXPatch::ApplyElement(
@@ -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;

+ 3 - 0
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);
 

+ 45 - 7
Source/CPack/WiX/cmWIXPatchParser.cxx

@@ -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,

+ 27 - 2
Source/CPack/WiX/cmWIXPatchParser.h

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

+ 19 - 0
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)
 {

+ 2 - 0
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);