diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 0cd692b4a42400ab14d2cfe3952954634c46beba..e7d095084632061b12ba27c235662498f11984c7 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -2780,7 +2780,8 @@ LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build");
 bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node)
 {
 	Params params(LLUICtrlFactory::getDefaultParams<LLFloater>());
-	LLXUIParser::instance().readXUI(node, params, filename); // *TODO: Error checking
+	LLXUIParser parser;
+	parser.readXUI(node, params, filename); // *TODO: Error checking
 
 	if (output_node)
 	{
@@ -2788,8 +2789,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
 		setupParamsForExport(output_params, parent);
         Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>());
 		output_node->setName(node->getName()->mString);
-		LLXUIParser::instance().writeXUI(
-			output_node, output_params, &default_params);
+		parser.writeXUI(output_node, output_params, &default_params);
 	}
 
 	// Default floater position to top-left corner of screen
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 45120913714199b457d70a5a77f837c30fc9686c..2e6e4912bfcbec8790ea9c73fe1514bceef10d45 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -238,7 +238,8 @@ static void get_attribute_bool_and_write(LLXMLNodePtr node,
 LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
 {
 	LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
-	LLXUIParser::instance().readXUI(node, p, LLUICtrlFactory::getInstance()->getCurFileName());
+	LLXUIParser parser;
+	parser.readXUI(node, p, LLUICtrlFactory::getInstance()->getCurFileName());
 
 	// Export must happen before setupParams() mungles rectangles and before
 	// this item gets added to parent (otherwise screws up last_child_rect
@@ -249,8 +250,7 @@ LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
 		setupParamsForExport(output_params, parent);
 		LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
 		output_node->setName(node->getName()->mString);
-		LLXUIParser::instance().writeXUI(
-			output_node, output_params, &default_params);
+		parser.writeXUI(output_node, output_params, &default_params);
 	}
 
 	p.from_xui = true;
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 51c8f6c743c00e96dcac13672dcc2f7d6d9ab04d..4471f315c0bb72d5c2adfbe7f2fb143688be853a 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -389,8 +389,7 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
 
 	LLPanel* panelp = NULL;
 	
-	{
-		LLFastTimer timer(FTM_PANEL_CONSTRUCTION);
+	{	LLFastTimer _(FTM_PANEL_CONSTRUCTION);
 		
 		if(!class_attr.empty())
 		{
@@ -512,6 +511,8 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
 			setXMLFilename(xml_filename);
 		}
 
+		LLXUIParser parser;
+
 		if (!xml_filename.empty())
 		{
 			LLUICtrlFactory::instance().pushFileName(xml_filename);
@@ -521,12 +522,11 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
 			{
 				//if we are exporting, we want to export the current xml
 				//not the referenced xml
-				LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+				parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
 				Params output_params(params);
 				setupParamsForExport(output_params, parent);
 				output_node->setName(node->getName()->mString);
-				LLXUIParser::instance().writeXUI(
-					output_node, output_params, &default_params);
+				parser.writeXUI(output_node, output_params, &default_params);
 				return TRUE;
 			}
 		
@@ -537,7 +537,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
 				return FALSE;
 			}
 
-			LLXUIParser::instance().readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
+			parser.readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
 
 			// add children using dimensions from referenced xml for consistent layout
 			setShape(params.rect);
@@ -547,15 +547,14 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
 		}
 
 		// ask LLUICtrlFactory for filename, since xml_filename might be empty
-		LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+		parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
 
 		if (output_node)
 		{
 			Params output_params(params);
 			setupParamsForExport(output_params, parent);
 			output_node->setName(node->getName()->mString);
-			LLXUIParser::instance().writeXUI(
-				output_node, output_params, &default_params);
+			parser.writeXUI(output_node, output_params, &default_params);
 		}
 		
 		params.from_xui = true;
diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp
index 7e3d4b92d3ddc5fdc08f4b26815bf351de24c6ae..718c10d2f800dded73413b156dcc24ff763451d8 100644
--- a/indra/llui/llrngwriter.cpp
+++ b/indra/llui/llrngwriter.cpp
@@ -36,10 +36,15 @@
 #include "lluicolor.h"
 #include "lluictrlfactory.h"
 
+static 	LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
+
 //
 // LLRNGWriter - writes Relax NG schema files based on a param block
 //
 LLRNGWriter::LLRNGWriter()
+: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
 {
 	// register various callbacks for inspecting the contents of a param block
 	registerInspectFunc<bool>(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4));
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index d356f061f93ce12a6adad2588232f8f205125e24..844278e41c6c0de261563a5b7cf5860919e1f903 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -2568,7 +2568,8 @@ BOOL	LLScrollListCtrl::canDeselect() const
 void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
 {
 	LLScrollListColumn::Params p;
-	LLParamSDParser::instance().readSD(column, p);
+	LLParamSDParser parser;
+	parser.readSD(column, p);
 	addColumn(p, pos);
 }
 
@@ -2759,7 +2760,8 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition
 {
 	LLFastTimer _(FTM_ADD_SCROLLLIST_ELEMENT);
 	LLScrollListItem::Params item_params;
-	LLParamSDParser::instance().readSD(element, item_params);
+	LLParamSDParser parser;
+	parser.readSD(element, item_params);
 	item_params.userdata = userdata;
 	return addRow(item_params, pos);
 }
diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp
index 7d37127584901977c4271661c3304f7612fb501e..338569fc588b4c2ec40fcf71f6d43eea141673bf 100644
--- a/indra/llui/llsdparam.cpp
+++ b/indra/llui/llsdparam.cpp
@@ -36,23 +36,31 @@
 // Project includes
 #include "llsdparam.h"
 
+static 	LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
+
 //
 // LLParamSDParser
 //
 LLParamSDParser::LLParamSDParser()
+: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
 {
 	using boost::bind;
 
-	registerParserFuncs<S32>(readS32, bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
-	registerParserFuncs<U32>(readU32, bind(&LLParamSDParser::writeU32Param, this, _1, _2));
-	registerParserFuncs<F32>(readF32, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
-	registerParserFuncs<F64>(readF64, bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
-	registerParserFuncs<bool>(readBool, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
-	registerParserFuncs<std::string>(readString, bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
-	registerParserFuncs<LLUUID>(readUUID, bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
-	registerParserFuncs<LLDate>(readDate, bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
-	registerParserFuncs<LLURI>(readURI, bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
-	registerParserFuncs<LLSD>(readSD, bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
+	if (sReadFuncs.empty())
+	{
+		registerParserFuncs<S32>(readS32, bind(&LLParamSDParser::writeTypedValue<S32>, this, _1, _2));
+		registerParserFuncs<U32>(readU32, bind(&LLParamSDParser::writeU32Param, this, _1, _2));
+		registerParserFuncs<F32>(readF32, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+		registerParserFuncs<F64>(readF64, bind(&LLParamSDParser::writeTypedValue<F64>, this, _1, _2));
+		registerParserFuncs<bool>(readBool, bind(&LLParamSDParser::writeTypedValue<F32>, this, _1, _2));
+		registerParserFuncs<std::string>(readString, bind(&LLParamSDParser::writeTypedValue<std::string>, this, _1, _2));
+		registerParserFuncs<LLUUID>(readUUID, bind(&LLParamSDParser::writeTypedValue<LLUUID>, this, _1, _2));
+		registerParserFuncs<LLDate>(readDate, bind(&LLParamSDParser::writeTypedValue<LLDate>, this, _1, _2));
+		registerParserFuncs<LLURI>(readURI, bind(&LLParamSDParser::writeTypedValue<LLURI>, this, _1, _2));
+		registerParserFuncs<LLSD>(readSD, bind(&LLParamSDParser::writeTypedValue<LLSD>, this, _1, _2));
+	}
 }
 
 // special case handling of U32 due to ambiguous LLSD::assign overload
diff --git a/indra/llui/llsdparam.h b/indra/llui/llsdparam.h
index d8af3c9bce3c2dc14e851fc8e203e3705ac89985..e98318fc1eae938d440b6dcfb0653082e8ebc395 100644
--- a/indra/llui/llsdparam.h
+++ b/indra/llui/llsdparam.h
@@ -37,17 +37,14 @@
 #include "llinitparam.h"
 
 class LLParamSDParser 
-:	public LLInitParam::Parser, 
-	public LLSingleton<LLParamSDParser>
+:	public LLInitParam::Parser
 {
 LOG_CLASS(LLParamSDParser);
 
 typedef LLInitParam::Parser parser_t;
 
-protected:
-	LLParamSDParser();
-	friend class LLSingleton<LLParamSDParser>;
 public:
+	LLParamSDParser();
 	void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
 	void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
 
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 5d8b628776169daef751170649b231c1551add9f..85fdfbb312f69845f46b12c293bc44e952822fed 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1802,7 +1802,8 @@ void LLUI::setupPaths()
 	LLXMLNodePtr root;
 	BOOL success  = LLXMLNode::parseFile(filename, root, NULL);
 	Paths paths;
-	LLXUIParser::instance().readXUI(root, paths, filename);
+	LLXUIParser parser;
+	parser.readXUI(root, paths, filename);
 
 	sXUIPaths.clear();
 	
diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp
index 1b64ef3abeaea97a533eb76463d2eac2cc6b8090..88140f1a49c4d0810e7ba67437c5116c3a83fe44 100644
--- a/indra/llui/lluicolortable.cpp
+++ b/indra/llui/lluicolortable.cpp
@@ -243,7 +243,8 @@ void LLUIColorTable::saveUserSettings() const
 	}
 
 	LLXMLNodePtr output_node = new LLXMLNode("colors", false);
-	LLXUIParser::instance().writeXUI(output_node, params);
+	LLXUIParser parser;
+	parser.writeXUI(output_node, params);
 
 	if(!output_node->isNull())
 	{
@@ -309,7 +310,8 @@ bool LLUIColorTable::loadFromFilename(const std::string& filename, string_color_
 	}
 
 	Params params;
-	LLXUIParser::instance().readXUI(root, params, filename);
+	LLXUIParser parser;
+	parser.readXUI(root, params, filename);
 
 	if(params.validateBlock())
 	{
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index ee700ee6ebb50a8431e39cfa282a70b314a67b25..2a2fa21ec0d6a2ae1c7a9c85f575a02ae43781fe 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -103,7 +103,8 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa
 	if (!full_filename.empty())
 	{
 		LLUICtrlFactory::instance().pushFileName(full_filename);
-		LLSimpleXUIParser::instance().readXUI(full_filename, block);
+		LLSimpleXUIParser parser;
+		parser.readXUI(full_filename, block);
 		LLUICtrlFactory::instance().popFileName();
 	}
 }
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 82076335d732d91d887cbc45663f2c2b1a6b6ccf..165c117088b2c6f5f161dab946041fdf703ebb7c 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -271,7 +271,8 @@ class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
 
 		typename T::Params params(getDefaultParams<T>());
 
-		LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
+		LLXUIParser parser;
+		parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
 
 		if (output_node)
 		{
@@ -281,8 +282,7 @@ class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
 			// Export only the differences between this any default params
 			typename T::Params default_params(getDefaultParams<T>());
 			copyName(node, output_node);
-			LLXUIParser::instance().writeXUI(
-				output_node, output_params, &default_params);
+			parser.writeXUI(output_node, output_params, &default_params);
 		}
 
 		// Apply layout transformations, usually munging rect
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 3ee4a85de0b29cc2b6814a7a583a651c834862d1..48db873b6f4dec0351c6cd0f087e69f2761772ad 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -111,8 +111,8 @@ LLView::Params::Params()
 	user_resize("user_resize"),
 	auto_resize("auto_resize"),
 	needs_translate("translate"),
-	min_width("min_width"),
-	max_width("max_width"),
+	min_dim("min_width"),
+	max_dim("max_width"),
 	xmlns("xmlns"),
 	xmlns_xsi("xmlns:xsi"),
 	xsi_schemaLocation("xsi:schemaLocation"),
@@ -120,6 +120,8 @@ LLView::Params::Params()
 
 {
 	addSynonym(rect, "");
+	addSynonym(min_dim, "min_height");
+	addSynonym(max_dim, "max_height");
 }
 
 LLView::LLView(const LLView::Params& p)
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 0f796fb40827e288ac15f2842fb1157560c2fb1c..6736ad9f33e724c0e502f7a8e730b0e9ccef9a97 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -145,16 +145,18 @@ class LLView : public LLMouseHandler, public LLMortician, public LLFocusableElem
 									left_delta;		// from last left to my left
 
 		//FIXME: get parent context involved in parsing traversal
-		Ignored						user_resize,		// nested attribute for LLLayoutPanel
-									auto_resize,		// nested attribute for LLLayoutPanel
-									needs_translate,	// cue for translation tools
-									min_width,			// nested attribute for LLLayoutPanel
-									max_width,			// nested attribute for LLLayoutPanel
+		Ignored						needs_translate;	// cue for translation tools
 									xmlns,				// xml namespace
 									xmlns_xsi,			// xml namespace
 									xsi_schemaLocation,	// xml schema
 									xsi_type;			// xml schema type
 
+		// nested attributes for LLLayoutPanel
+		Optional<S32>				min_dim,
+									max_dim;
+		Optional<bool>				user_resize,		
+									auto_resize;
+
 		Params();
 	};
 
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index 5461ad9d053e8906188ad96992baf3f324f1b1bb..488e20cf9fcfd27fffdd1e188261b3abbeb7a5ac 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -204,14 +204,14 @@ namespace LLInitParam
 		typedef std::vector<std::string>							possible_values_t;
 
 		typedef bool (*parser_read_func_t)(Parser& parser, void* output);
-		typedef boost::function<bool (const void*, const name_stack_t&)>								parser_write_func_t;
+		typedef bool (*parser_write_func_t)(Parser& parser, const void*, const name_stack_t&);
 		typedef boost::function<void (const name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 
 		typedef std::map<const std::type_info*, parser_read_func_t, CompareTypeID>		parser_read_func_map_t;
 		typedef std::map<const std::type_info*, parser_write_func_t, CompareTypeID>		parser_write_func_map_t;
 		typedef std::map<const std::type_info*, parser_inspect_func_t, CompareTypeID>	parser_inspect_func_map_t;
 
-		Parser()
+		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
 		:	mParseSilently(false),
 			mParseGeneration(0)
 		{}
@@ -219,8 +219,8 @@ namespace LLInitParam
 
 		template <typename T> bool readValue(T& param)
 	    {
-		    parser_read_func_map_t::iterator found_it = mParserReadFuncs.find(&typeid(T));
-		    if (found_it != mParserReadFuncs.end())
+		    parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+		    if (found_it != mParserReadFuncs->end())
 		    {
 			    return found_it->second(*this, (void*)&param);
 		    }
@@ -229,10 +229,10 @@ namespace LLInitParam
 
 		template <typename T> bool writeValue(const T& param, const name_stack_t& name_stack)
 		{
-		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs.find(&typeid(T));
-		    if (found_it != mParserWriteFuncs.end())
+		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+		    if (found_it != mParserWriteFuncs->end())
 		    {
-			    return found_it->second((const void*)&param, name_stack);
+			    return found_it->second(*this, (const void*)&param, name_stack);
 		    }
 		    return false;
 		}
@@ -240,8 +240,8 @@ namespace LLInitParam
 		// dispatch inspection to registered inspection functions, for each parameter in a param block
 		template <typename T> bool inspectValue(const name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
 		{
-		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs.find(&typeid(T));
-		    if (found_it != mParserInspectFuncs.end())
+		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+		    if (found_it != mParserInspectFuncs->end())
 		    {
 			    found_it->second(name_stack, min_count, max_count, possible_values);
 				return true;
@@ -253,7 +253,6 @@ namespace LLInitParam
 		virtual void parserWarning(const std::string& message);
 		virtual void parserError(const std::string& message);
 		void setParseSilently(bool silent) { mParseSilently = silent; }
-		bool getParseSilently() { return mParseSilently; }
 
 		S32 getParseGeneration() { return mParseGeneration; }
 		S32 newParseGeneration() { return ++mParseGeneration; }
@@ -261,24 +260,24 @@ namespace LLInitParam
 
 	protected:
 		template <typename T>
-		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func)
+		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
 		{
-			mParserReadFuncs.insert(std::make_pair(&typeid(T), read_func));
-			mParserWriteFuncs.insert(std::make_pair(&typeid(T), write_func));
+			mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
+			mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
 		}
 
 		template <typename T>
 		void registerInspectFunc(parser_inspect_func_t inspect_func)
 		{
-			mParserInspectFuncs.insert(std::make_pair(&typeid(T), inspect_func));
+			mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
 		}
 
 		bool				mParseSilently;
 
 	private:
-		parser_read_func_map_t		mParserReadFuncs;
-		parser_write_func_map_t		mParserWriteFuncs;
-		parser_inspect_func_map_t	mParserInspectFuncs;
+		parser_read_func_map_t*		mParserReadFuncs;
+		parser_write_func_map_t*	mParserWriteFuncs;
+		parser_inspect_func_map_t*	mParserInspectFuncs;
 		S32	mParseGeneration;
 	};
 
@@ -581,7 +580,7 @@ namespace LLInitParam
 			// no further names in stack, attempt to parse value now
 			if (name_stack.first == name_stack.second)
 			{
-				if (parser.readValue<T>(typed_param.mData.mValue))
+				if (parser.readValue(typed_param.mData.mValue))
 				{
 					typed_param.mData.clearKey();
 					typed_param.setProvided(true);
@@ -594,7 +593,7 @@ namespace LLInitParam
 				{
 					// try to parse a known named value
 					std::string name;
-					if (parser.readValue<std::string>(name))
+					if (parser.readValue(name))
 					{
 						// try to parse a per type named value
 						if (NAME_VALUE_LOOKUP::get(name, typed_param.mData.mValue))
@@ -629,7 +628,7 @@ namespace LLInitParam
 			{
 				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key))
 				{
-					if (!parser.writeValue<std::string>(key, name_stack))
+					if (!parser.writeValue(key, name_stack))
 					{
 						return;
 					}
@@ -637,7 +636,7 @@ namespace LLInitParam
 			}
 			// then try to serialize value directly
 			else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), static_cast<const self_t*>(diff_param)->get()))					{
-				if (!parser.writeValue<T>(typed_param.mData.mValue, name_stack)) 
+				if (!parser.writeValue(typed_param.mData.mValue, name_stack)) 
 				{
 					return;
 				}
@@ -750,7 +749,7 @@ namespace LLInitParam
 			{
 				// try to parse a known named value
 				std::string name;
-				if (parser.readValue<std::string>(name))
+				if (parser.readValue(name))
 				{
 					// try to parse a per type named value
 					if (NAME_VALUE_LOOKUP::get(name, typed_param))
@@ -777,7 +776,7 @@ namespace LLInitParam
 			std::string key = typed_param.mData.getKey();
 			if (!key.empty() && typed_param.mData.mKeyVersion == typed_param.getLastChangeVersion())
 			{
-				if (!parser.writeValue<std::string>(key, name_stack))
+				if (!parser.writeValue(key, name_stack))
 				{
 					return;
 				}
@@ -924,7 +923,7 @@ namespace LLInitParam
 			if (name_stack.first == name_stack.second)
 			{
 				// attempt to read value directly
-				if (parser.readValue<value_t>(value))
+				if (parser.readValue(value))
 				{
 					typed_param.mValues.push_back(value);
 					// save an empty name/value key as a placeholder
@@ -939,7 +938,7 @@ namespace LLInitParam
 				{
 					// try to parse a known named value
 					std::string name;
-					if (parser.readValue<std::string>(name))
+					if (parser.readValue(name))
 					{
 						// try to parse a per type named value
 						if (NAME_VALUE_LOOKUP::get(name, typed_param.mValues))
@@ -973,13 +972,13 @@ namespace LLInitParam
 
 				if(!key.empty())
 				{
-					if(!parser.writeValue<std::string>(key, name_stack))
+					if(!parser.writeValue(key, name_stack))
 					{
 						return;
 					}
 				}
 				// not parse via name values, write out value directly
-				else if (!parser.writeValue<VALUE_TYPE>(*it, name_stack))
+				else if (!parser.writeValue(*it, name_stack))
 				{
 					return;
 				}
@@ -1126,7 +1125,7 @@ namespace LLInitParam
 			{
 				// try to parse a known named value
 				std::string name;
-				if (parser.readValue<std::string>(name))
+				if (parser.readValue(name))
 				{
 					// try to parse a per type named value
 					if (NAME_VALUE_LOOKUP::get(name, value))
@@ -1159,7 +1158,7 @@ namespace LLInitParam
 				std::string key = key_it->getKey();
 				if (!key.empty() && key_it->mKeyVersion == it->getLastChangeVersion())
 				{
-					if(!parser.writeValue<std::string>(key, name_stack))
+					if(!parser.writeValue(key, name_stack))
 					{
 						return;
 					}
@@ -1624,7 +1623,7 @@ namespace LLInitParam
 			// type to apply parse direct value T
 			if (name_stack.first == name_stack.second)
 			{
-				if(parser.readValue<T>(typed_param.mData.mValue))
+				if(parser.readValue(typed_param.mData.mValue))
 				{
 					typed_param.enclosingBlock().setLastChangedParam(param, true);
 					typed_param.setProvided(true);
@@ -1639,7 +1638,7 @@ namespace LLInitParam
 				{
 					// try to parse a known named value
 					std::string name;
-					if (parser.readValue<std::string>(name))
+					if (parser.readValue(name))
 					{
 						// try to parse a per type named value
 						if (TypeValues<T>::get(name, typed_param.mData.mValue))
@@ -1681,7 +1680,7 @@ namespace LLInitParam
 			{
 				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key))
 				{
-					if (!parser.writeValue<std::string>(key, name_stack))
+					if (!parser.writeValue(key, name_stack))
 					{
 						return;
 					}
@@ -1691,7 +1690,7 @@ namespace LLInitParam
 			else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), (static_cast<const self_t*>(diff_param))->get()))	
             {
 				
-				if (parser.writeValue<T>(typed_param.mData.mValue, name_stack)) 
+				if (parser.writeValue(typed_param.mData.mValue, name_stack)) 
 				{
 					return;
 				}
diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp
index d6f17dbb085779b71ed29e2ff9ff527647f98ca8..bf38e925c6156e23f6e36b5c696f2c708d5d28ce 100644
--- a/indra/llxuixml/lltrans.cpp
+++ b/indra/llxuixml/lltrans.cpp
@@ -72,7 +72,8 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa
 	}
 
 	StringTable string_table;
-	LLXUIParser::instance().readXUI(root, string_table, xml_filename);
+	LLXUIParser parser;
+	parser.readXUI(root, string_table, xml_filename);
 
 	if (!string_table.validateBlock())
 	{
@@ -115,7 +116,8 @@ bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
 	}
 	
 	StringTable string_table;
-	LLXUIParser::instance().readXUI(root, string_table, xml_filename);
+	LLXUIParser parser;
+	parser.readXUI(root, string_table, xml_filename);
 	
 	if (!string_table.validateBlock())
 	{
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
index d856efb008110a8e7a8d3ff2b81bc20c5ad5eee1..220171fb79944c46a51cc0f483bb74b1ae5395f1 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -47,10 +47,16 @@ using namespace BOOST_SPIRIT_CLASSIC_NS;
 
 const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;
 
+static 	LLInitParam::Parser::parser_read_func_map_t sXSDReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sXSDWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sXSDInspectFuncs;
+
+
 //
 // LLXSDWriter
 //
 LLXSDWriter::LLXSDWriter()
+: Parser(sXSDReadFuncs, sXSDWriteFuncs, sXSDInspectFuncs)
 {
 	registerInspectFunc<bool>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:boolean", _1, _2, _3, _4));
 	registerInspectFunc<std::string>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4));
@@ -368,27 +374,35 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p
 	fclose(xsd_file);
 }
 
+static 	LLInitParam::Parser::parser_read_func_map_t sXUIReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sXUIWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sXUIInspectFuncs;
+
 //
 // LLXUIParser
 //
 LLXUIParser::LLXUIParser()
-:	mLastWriteGeneration(-1),
+:	Parser(sXUIReadFuncs, sXUIWriteFuncs, sXUIInspectFuncs),
+	mLastWriteGeneration(-1),
 	mCurReadDepth(0)
 {
-	registerParserFuncs<bool>(readBoolValue, boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2));
-	registerParserFuncs<std::string>(readStringValue, boost::bind(&LLXUIParser::writeStringValue, this, _1, _2));
-	registerParserFuncs<U8>(readU8Value, boost::bind(&LLXUIParser::writeU8Value, this, _1, _2));
-	registerParserFuncs<S8>(readS8Value, boost::bind(&LLXUIParser::writeS8Value, this, _1, _2));
-	registerParserFuncs<U16>(readU16Value, boost::bind(&LLXUIParser::writeU16Value, this, _1, _2));
-	registerParserFuncs<S16>(readS16Value, boost::bind(&LLXUIParser::writeS16Value, this, _1, _2));
-	registerParserFuncs<U32>(readU32Value, boost::bind(&LLXUIParser::writeU32Value, this, _1, _2));
-	registerParserFuncs<S32>(readS32Value, boost::bind(&LLXUIParser::writeS32Value, this, _1, _2));
-	registerParserFuncs<F32>(readF32Value, boost::bind(&LLXUIParser::writeF32Value, this, _1, _2));
-	registerParserFuncs<F64>(readF64Value, boost::bind(&LLXUIParser::writeF64Value, this, _1, _2));
-	registerParserFuncs<LLColor4>(readColor4Value, boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2));
-	registerParserFuncs<LLUIColor>(readUIColorValue, boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2));
-	registerParserFuncs<LLUUID>(readUUIDValue, boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2));
-	registerParserFuncs<LLSD>(readSDValue, boost::bind(&LLXUIParser::writeSDValue, this, _1, _2));
+	if (sXUIReadFuncs.empty())
+	{
+		registerParserFuncs<bool>(readBoolValue, writeBoolValue);
+		registerParserFuncs<std::string>(readStringValue, writeStringValue);
+		registerParserFuncs<U8>(readU8Value, writeU8Value);
+		registerParserFuncs<S8>(readS8Value, writeS8Value);
+		registerParserFuncs<U16>(readU16Value, writeU16Value);
+		registerParserFuncs<S16>(readS16Value, writeS16Value);
+		registerParserFuncs<U32>(readU32Value, writeU32Value);
+		registerParserFuncs<S32>(readS32Value, writeS32Value);
+		registerParserFuncs<F32>(readF32Value, writeF32Value);
+		registerParserFuncs<F64>(readF64Value, writeF64Value);
+		registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value);
+		registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue);
+		registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue);
+		registerParserFuncs<LLSD>(readSDValue, writeSDValue);
+	}
 }
 
 static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
@@ -621,9 +635,10 @@ bool LLXUIParser::readBoolValue(Parser& parser, void* val_ptr)
 	return success;
 }
 
-bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeBoolValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setBoolValue(*((bool*)val_ptr));
@@ -639,9 +654,10 @@ bool LLXUIParser::readStringValue(Parser& parser, void* val_ptr)
 	return true;
 }
 
-bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeStringValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		const std::string* string_val = reinterpret_cast<const std::string*>(val_ptr);
@@ -676,9 +692,10 @@ bool LLXUIParser::readU8Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getByteValue(1, (U8*)val_ptr);
 }
 
-bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU8Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setUnsignedValue(*((U8*)val_ptr));
@@ -699,9 +716,10 @@ bool LLXUIParser::readS8Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS8Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setIntValue(*((S8*)val_ptr));
@@ -722,9 +740,10 @@ bool LLXUIParser::readU16Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU16Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setUnsignedValue(*((U16*)val_ptr));
@@ -745,9 +764,10 @@ bool LLXUIParser::readS16Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS16Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setIntValue(*((S16*)val_ptr));
@@ -762,9 +782,10 @@ bool LLXUIParser::readU32Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
 }
 
-bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeU32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setUnsignedValue(*((U32*)val_ptr));
@@ -779,9 +800,10 @@ bool LLXUIParser::readS32Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getIntValue(1, (S32*)val_ptr);
 }
 
-bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeS32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setIntValue(*((S32*)val_ptr));
@@ -796,9 +818,10 @@ bool LLXUIParser::readF32Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getFloatValue(1, (F32*)val_ptr);
 }
 
-bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeF32Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setFloatValue(*((F32*)val_ptr));
@@ -813,9 +836,10 @@ bool LLXUIParser::readF64Value(Parser& parser, void* val_ptr)
 	return self.mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
 }
 
-bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setDoubleValue(*((F64*)val_ptr));
@@ -836,9 +860,10 @@ bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeColor4Value(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		LLColor4 color = *((LLColor4*)val_ptr);
@@ -862,9 +887,10 @@ bool LLXUIParser::readUIColorValue(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeUIColorValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		LLUIColor color = *((LLUIColor*)val_ptr);
@@ -890,9 +916,10 @@ bool LLXUIParser::readUUIDValue(Parser& parser, void* val_ptr)
 	return false;
 }
 
-bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeUUIDValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		node->setStringValue(((LLUUID*)val_ptr)->asString());
@@ -908,9 +935,11 @@ bool LLXUIParser::readSDValue(Parser& parser, void* val_ptr)
 	return true;
 }
 
-bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack)
+bool LLXUIParser::writeSDValue(Parser& parser, const void* val_ptr, const name_stack_t& stack)
 {
-	LLXMLNodePtr node = getNode(stack);
+	LLXUIParser& self = static_cast<LLXUIParser&>(parser);
+
+	LLXMLNodePtr node = self.getNode(stack);
 	if (node.notNull())
 	{
 		std::string string_val = ((LLSD*)val_ptr)->asString();
@@ -1007,25 +1036,33 @@ struct ScopedFile
 
 	LLFILE* mFile;
 };
+static 	LLInitParam::Parser::parser_read_func_map_t sSimpleXUIReadFuncs;
+static 	LLInitParam::Parser::parser_write_func_map_t sSimpleXUIWriteFuncs;
+static 	LLInitParam::Parser::parser_inspect_func_map_t sSimpleXUIInspectFuncs;
 
-LLSimpleXUIParser::LLSimpleXUIParser()
-:	mLastWriteGeneration(-1),
-	mCurReadDepth(0)
+LLSimpleXUIParser::LLSimpleXUIParser(LLSimpleXUIParser::element_start_callback_t element_cb)
+:	Parser(sSimpleXUIReadFuncs, sSimpleXUIWriteFuncs, sSimpleXUIInspectFuncs),
+	mLastWriteGeneration(-1),
+	mCurReadDepth(0),
+	mElementCB(element_cb)
 {
-	registerParserFuncs<bool>(readBoolValue, NULL);
-	registerParserFuncs<std::string>(readStringValue, NULL);
-	registerParserFuncs<U8>(readU8Value, NULL);
-	registerParserFuncs<S8>(readS8Value, NULL);
-	registerParserFuncs<U16>(readU16Value, NULL);
-	registerParserFuncs<S16>(readS16Value, NULL);
-	registerParserFuncs<U32>(readU32Value, NULL);
-	registerParserFuncs<S32>(readS32Value, NULL);
-	registerParserFuncs<F32>(readF32Value, NULL);
-	registerParserFuncs<F64>(readF64Value, NULL);
-	registerParserFuncs<LLColor4>(readColor4Value, NULL);
-	registerParserFuncs<LLUIColor>(readUIColorValue, NULL);
-	registerParserFuncs<LLUUID>(readUUIDValue, NULL);
-	registerParserFuncs<LLSD>(readSDValue, NULL);
+	if (sSimpleXUIReadFuncs.empty())
+	{
+		registerParserFuncs<bool>(readBoolValue);
+		registerParserFuncs<std::string>(readStringValue);
+		registerParserFuncs<U8>(readU8Value);
+		registerParserFuncs<S8>(readS8Value);
+		registerParserFuncs<U16>(readU16Value);
+		registerParserFuncs<S16>(readS16Value);
+		registerParserFuncs<U32>(readU32Value);
+		registerParserFuncs<S32>(readS32Value);
+		registerParserFuncs<F32>(readF32Value);
+		registerParserFuncs<F64>(readF64Value);
+		registerParserFuncs<LLColor4>(readColor4Value);
+		registerParserFuncs<LLUIColor>(readUIColorValue);
+		registerParserFuncs<LLUUID>(readUUIDValue);
+		registerParserFuncs<LLSD>(readSDValue);
+	}
 }
 
 LLSimpleXUIParser::~LLSimpleXUIParser()
@@ -1042,7 +1079,7 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl
 	XML_SetElementHandler(			mParser,	startElementHandler, endElementHandler);
 	XML_SetCharacterDataHandler(	mParser,	characterDataHandler);
 
-	mBlock = &block;
+	mOutputStack.push_back(std::make_pair(&block, 0));
 	mNameStack.clear();
 	mCurFileName = filename;
 	mCurReadDepth = 0;
@@ -1108,16 +1145,25 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts)
 	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
 	boost::char_separator<char> sep(".");
 
-	mCurReadDepth++;
+	if (mElementCB) 
+	{
+		LLInitParam::BaseBlock* blockp = mElementCB(*this, name);
+		if (blockp)
+		{
+			mOutputStack.push_back(std::make_pair(blockp, 0));
+		}
+	}
+
+	mOutputStack.back().second++;
 	S32 num_tokens_pushed = 0;
 	std::string child_name(name);
 
-	if (mCurReadDepth > 1)
-	{
-		// for non "dotted" child nodes	check to see if child node maps to another widget type
-		// and if not, treat as a child element of the current node
-		// e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect"
-		// since there is no widget named "rect"
+	if (mOutputStack.back().second == 1)
+	{	// root node for this block
+		mScope.push_back(child_name);
+	}
+	else
+	{	// compound attribute
 		if (child_name.find(".") == std::string::npos) 
 		{
 			mNameStack.push_back(std::make_pair(child_name, newParseGeneration()));
@@ -1153,10 +1199,6 @@ void LLSimpleXUIParser::startElement(const char *name, const char **atts)
 			mScope.push_back(mNameStack.back().first);
 		}
 	}
-	else
-	{
-		mScope.push_back(child_name);
-	}
 
 	mTokenSizeStack.push_back(num_tokens_pushed);
 	readAttributes(atts);
@@ -1183,8 +1225,7 @@ bool LLSimpleXUIParser::readAttributes(const char **atts)
 		}
 
 		// child nodes are not necessarily valid attributes, so don't complain once we've recursed
-		bool silent = mCurReadDepth > 1;
-		any_parsed |= mBlock->submitValue(mNameStack, *this, silent);
+		any_parsed |= mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
 		
 		while(num_tokens_pushed-- > 0)
 		{
@@ -1204,12 +1245,21 @@ void LLSimpleXUIParser::endElement(const char *name)
 		{
 			mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
 			mCurAttributeValueBegin = mTextContents.c_str();
-			mBlock->submitValue(mNameStack, *this, false);
+			mOutputStack.back().first->submitValue(mNameStack, *this, mParseSilently);
 			mNameStack.pop_back();
 			mTextContents.clear();
 		}
 	}
-	mCurReadDepth--;
+
+	if (--mOutputStack.back().second == 0)
+	{
+		if (mOutputStack.empty())
+		{
+			LL_ERRS("ReadXUI") << "Parameter block output stack popped while empty." << LL_ENDL;
+		}
+		mOutputStack.pop_back();
+	}
+
 	S32 num_tokens_to_pop = mTokenSizeStack.back();
 	mTokenSizeStack.pop_back();
 	while(num_tokens_to_pop-- > 0)
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
index eb7147f49ea71f25f8ce77c6fdc0266f97e90a3e..ee8fcdc369fa9959db61185ed2cd66750b4b7695 100644
--- a/indra/llxuixml/llxuiparser.h
+++ b/indra/llxuixml/llxuiparser.h
@@ -102,14 +102,12 @@ class LLXUIXSDWriter : public LLXSDWriter
 
 
 
-class LLXUIParser : public LLInitParam::Parser, public LLSingleton<LLXUIParser>
+class LLXUIParser : public LLInitParam::Parser
 {
 LOG_CLASS(LLXUIParser);
 
-protected:
-	LLXUIParser();
-	friend class LLSingleton<LLXUIParser>;
 public:
+	LLXUIParser();
 	typedef LLInitParam::Parser::name_stack_t name_stack_t;
 
 	/*virtual*/ std::string getCurrentElementName();
@@ -140,20 +138,20 @@ LOG_CLASS(LLXUIParser);
 	static bool readSDValue(Parser& parser, void* val_ptr);
 
 	//writer helper functions
-	bool writeBoolValue(const void* val_ptr, const name_stack_t&);
-	bool writeStringValue(const void* val_ptr, const name_stack_t&);
-	bool writeU8Value(const void* val_ptr, const name_stack_t&);
-	bool writeS8Value(const void* val_ptr, const name_stack_t&);
-	bool writeU16Value(const void* val_ptr, const name_stack_t&);
-	bool writeS16Value(const void* val_ptr, const name_stack_t&);
-	bool writeU32Value(const void* val_ptr, const name_stack_t&);
-	bool writeS32Value(const void* val_ptr, const name_stack_t&);
-	bool writeF32Value(const void* val_ptr, const name_stack_t&);
-	bool writeF64Value(const void* val_ptr, const name_stack_t&);
-	bool writeColor4Value(const void* val_ptr, const name_stack_t&);
-	bool writeUIColorValue(const void* val_ptr, const name_stack_t&);
-	bool writeUUIDValue(const void* val_ptr, const name_stack_t&);
-	bool writeSDValue(const void* val_ptr, const name_stack_t&);
+	static bool writeBoolValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeStringValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeU8Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeS8Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeU16Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeS16Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeU32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeS32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeF32Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeF64Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeColor4Value(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeUIColorValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeUUIDValue(Parser& parser, const void* val_ptr, const name_stack_t&);
+	static bool writeSDValue(Parser& parser, const void* val_ptr, const name_stack_t&);
 
 	LLXMLNodePtr getNode(const name_stack_t& stack);
 
@@ -182,23 +180,22 @@ LOG_CLASS(LLXUIParser);
 // of coroutines to perform matching of xml nodes during parsing.  Not sure if the overhead
 // of coroutines would offset the gain from SAX parsing
 
-class LLSimpleXUIParser : public LLInitParam::Parser, public LLSingleton<LLSimpleXUIParser>
+class LLSimpleXUIParser : public LLInitParam::Parser
 {
 LOG_CLASS(LLSimpleXUIParser);
-
-protected:
-	LLSimpleXUIParser();
-	virtual ~LLSimpleXUIParser();
-	friend class LLSingleton<LLSimpleXUIParser>;
 public:
 	typedef LLInitParam::Parser::name_stack_t name_stack_t;
+	typedef LLInitParam::BaseBlock* (*element_start_callback_t)(LLSimpleXUIParser&, const char* block_name);
+
+	LLSimpleXUIParser(element_start_callback_t element_cb = NULL);
+	virtual ~LLSimpleXUIParser();
 
 	/*virtual*/ std::string getCurrentElementName();
 	/*virtual*/ void parserWarning(const std::string& message);
 	/*virtual*/ void parserError(const std::string& message);
 
 	bool readXUI(const std::string& filename, LLInitParam::BaseBlock& block, bool silent=false);
-	void setBlock(LLInitParam::BaseBlock* block);
+
 
 private:
 	//reader helper functions
@@ -227,7 +224,6 @@ LOG_CLASS(LLSimpleXUIParser);
 	void characterData(const char *s, int len);
 	bool readAttributes(const char **atts);
 
-	LLInitParam::BaseBlock*			mBlock;
 	Parser::name_stack_t			mNameStack;
 	struct XML_ParserStruct*		mParser;
 	S32								mLastWriteGeneration;
@@ -238,6 +234,9 @@ LOG_CLASS(LLSimpleXUIParser);
 	const char*						mCurAttributeValueBegin;
 	std::vector<S32>				mTokenSizeStack;
 	std::vector<std::string>		mScope;
+	element_start_callback_t		mElementCB;
+
+	std::vector<std::pair<LLInitParam::BaseBlock*, S32> > mOutputStack;
 };
 
 
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index b8776d0af2afb55aa1fcb184e2277587db6fdfaa..ef596c4457e766b1d43dac37dce20efcc4466395 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -677,7 +677,8 @@ const LLButton::Params& LLFavoritesBarCtrl::getButtonParams()
 		LLXMLNodePtr button_xml_node;
 		if(LLUICtrlFactory::getLayeredXMLNode("favorites_bar_button.xml", button_xml_node))
 		{
-			LLXUIParser::instance().readXUI(button_xml_node, button_params, "favorites_bar_button.xml");
+			LLXUIParser parser;
+			parser.readXUI(button_xml_node, button_params, "favorites_bar_button.xml");
 		}
 		params_initialized = true;
 	}
diff --git a/indra/newview/llhints.cpp b/indra/newview/llhints.cpp
index e0ced5caeb1cdfe1f97e398d2344e009b155aa91..4d7cdc01e52743429dab9c42fed3534369947413 100644
--- a/indra/newview/llhints.cpp
+++ b/indra/newview/llhints.cpp
@@ -297,7 +297,8 @@ void LLHints::show(LLNotificationPtr hint)
 {
 	LLHintPopup::Params p(LLUICtrlFactory::getDefaultParams<LLHintPopup>());
 
-	LLParamSDParser::instance().readSD(hint->getPayload(), p);
+	LLParamSDParser parser;
+	parser.readSD(hint->getPayload(), p);
 	p.notification = hint;
 
 	if (p.validateBlock())
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index d09f729943b77e4ce45e548e46b818d081e9f392..b4c4d4a2ee6dcc20c8d833789b74382bbd2315ca 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -259,7 +259,8 @@ void LLNameListCtrl::addNameItem(LLNameListCtrl::NameItem& item, EAddPosition po
 LLScrollListItem* LLNameListCtrl::addElement(const LLSD& element, EAddPosition pos, void* userdata)
 {
 	LLNameListCtrl::NameItem item_params;
-	LLParamSDParser::instance().readSD(element, item_params);
+	LLParamSDParser parser;
+	parser.readSD(element, item_params);
 	item_params.userdata = userdata;
 	return addNameItemRow(item_params, pos);
 }
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index d35739d436b8d959b56ca9216e5e89a52b63f08d..7429386871c9e43740f81f674b3bcea039a1e893 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -79,7 +79,8 @@ const LLAccordionCtrlTab::Params& get_accordion_tab_params()
 		LLXMLNodePtr xmlNode;
 		if (LLUICtrlFactory::getLayeredXMLNode("outfit_accordion_tab.xml", xmlNode))
 		{
-			LLXUIParser::instance().readXUI(xmlNode, tab_params, "outfit_accordion_tab.xml");
+			LLXUIParser parser;
+			parser.readXUI(xmlNode, tab_params, "outfit_accordion_tab.xml");
 		}
 		else
 		{
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 02097ea06d9f5c514a6ebcf63116ec7c14e8654f..181c5b4c810f8721c5c9690b51895efd97107be1 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1550,7 +1550,8 @@ bool LLUIImageList::initFromFile()
 	}
 
 	UIImageDeclarations images;
-	LLXUIParser::instance().readXUI(root, images, base_file_path);
+	LLXUIParser parser;
+	parser.readXUI(root, images, base_file_path);
 
 	if (!images.validateBlock()) return false;
 
diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml
index cae61468804f17ebf84fd7effd0a3ab85d8d97a2..930bbaa8cb10b74b80ce297f27bd71d56649c7fb 100644
--- a/indra/newview/skins/default/xui/en/floater_aaa.xml
+++ b/indra/newview/skins/default/xui/en/floater_aaa.xml
@@ -20,7 +20,7 @@
   <string name="nudge_parabuild" translate="false">Nudge 1</string>
   <string name="test_the_vlt">This string CHANGE2 is extracted.</string>
   <string name="testing_eli">Just a test. changes.</string>
-  <chat_history
+  <text_editor
    parse_urls="true"
    bg_readonly_color="ChatHistoryBgColor"
    bg_writeable_color="ChatHistoryBgColor" 
@@ -32,26 +32,51 @@
    layout="topleft"
 	 height="260"
    name="chat_history"
+   max_length="200000" 
    parse_highlights="true"
    text_color="ChatHistoryTextColor"
    text_readonly_color="ChatHistoryTextColor"
    translate="false"
+   track_end="true" 
+   wrap="true" 
    width="320">
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-Really long line that is long enough to wrap once with jyg descenders.
-  </chat_history>
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    Really long line that is long enough to wrap once with jyg descenders.
+    </text_editor>
 </floater>