void CGUIIncludes::ResolveIncludesForNode(TiXmlElement *node) { // we have a node, find any <include file="fileName">tagName</include> tags and replace // recursively with their real includes if (!node) return; // First add the defaults if this is for a control CStdString type; if (node->ValueStr() == "control") { type = node->Attribute("type"); map<CStdString, TiXmlElement>::const_iterator it = m_defaults.find(type); if (it != m_defaults.end()) { const TiXmlElement &element = (*it).second; const TiXmlElement *tag = element.FirstChildElement(); while (tag) { // we insert at the end of block node->InsertEndChild(*tag); tag = tag->NextSiblingElement(); } } } TiXmlElement *include = node->FirstChildElement("include"); while (include && include->FirstChild()) { // have an include tag - grab it's tag name and replace it with the real tag contents const char *file = include->Attribute("file"); if (file) { // we need to load this include from the alternative file LoadIncludes(g_SkinInfo->GetSkinPath(file)); } const char *condition = include->Attribute("condition"); if (condition) { // check this condition if (!g_infoManager.EvaluateBool(condition)) { include = include->NextSiblingElement("include"); continue; } } CStdString tagName = include->FirstChild()->Value(); map<CStdString, TiXmlElement>::const_iterator it = m_includes.find(tagName); if (it != m_includes.end()) { // found the tag(s) to include - let's replace it const TiXmlElement &element = (*it).second; const TiXmlElement *tag = element.FirstChildElement(); while (tag) { // we insert before the <include> element to keep the correct // order (we render in the order given in the xml file) node->InsertBeforeChild(include, *tag); tag = tag->NextSiblingElement(); } // remove the <include>tagName</include> element node->RemoveChild(include); include = node->FirstChildElement("include"); } else { // invalid include CLog::Log(LOGWARNING, "Skin has invalid include: %s", tagName.c_str()); include = include->NextSiblingElement("include"); } } // run through this element's attributes, resolving any constants TiXmlAttribute *attribute = node->FirstAttribute(); while (attribute) { // check the attribute against our set if (m_constantAttributes.count(attribute->NameStr())) attribute->SetValue(ResolveConstant(attribute->ValueStr())); attribute = attribute->Next(); } // also do the value if (node->FirstChild() && node->FirstChild()->Type() == TiXmlNode::TEXT && m_constantNodes.count(node->ValueStr())) node->FirstChild()->SetValue(ResolveConstant(node->FirstChild()->ValueStr())); }
const char* TiXmlElement::Parse ( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { p = SkipWhiteSpace( p, encoding ); TiXmlDocument* document = GetDocument(); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); return 0; } if ( data ) { data->Stamp( p, encoding ); location = data->Cursor(); } if ( *p != '<' ) { if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); return 0; } p = SkipWhiteSpace( p+1, encoding ); // Read the name. const char* pErr = p; p = ReadName( p, &value, encoding ); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding ); return 0; } String endTag ("</"); endTag += value; endTag += ">"; // Check for and read attributes. Also look for an empty // tag or an end tag. while ( p && *p ) { pErr = p; p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); return 0; } if ( *p == '/' ) { ++p; // Empty tag. if ( *p != '>' ) { if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding ); return 0; } return (p+1); } else if ( *p == '>' ) { // Done with attributes (if there were any.) // Read the value -- which can include other // elements -- read the end tag, and return. ++p; // Note this is an Element method, and will set the error if // one happens. p = ReadValue( p, data, encoding ); if ( !p || !*p ) { // We were looking for the end tag, but found nothing. // Fix for [ 1663758 ] Failure to report error on bad XML if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); return 0; } // We should find the end tag now if ( StringEqual( p, endTag.c_str(), false, encoding ) ) { p += endTag.length(); return p; } else { if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); return 0; } } else { // Try to read an attribute: TiXmlAttribute* attrib = new TiXmlAttribute(); if ( !attrib ) { if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding ); return 0; } attrib->SetDocument( document ); pErr = p; p = attrib->Parse( p, data, encoding ); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); delete attrib; return 0; } // Handle the strange case of double attributes by ignoring // all but the last one. // sherm 100319: I fixed this TiXmlAttribute* node = attributeSet.Find( attrib->NameStr() ); if ( node ) { node->SetValue( attrib->Value() ); delete attrib; } else attributeSet.Add( attrib ); } } return p; }