Gui: Escape XML special characters in attributes for XHTML

Add escapeXmlAttribute() helper function to properly escape special
characters in XML attribute values:
- Double quotes (") --> "
- Ampersands (&) --> &
- Less-than (<) --> &lt;
- Greater-than (>) --> &gt;
- Single quotes (') --> &apos;
This commit is contained in:
tetektoza
2025-12-27 18:51:01 +01:00
parent 679d4c2397
commit fe7bceeb79

View File

@@ -497,6 +497,43 @@ bool Gui::SoFCDB::writeToX3D(SoNode* node, bool exportViewpoints, std::string& b
return true;
}
namespace
{
std::string escapeXmlAttribute(const char* str)
{
if (!str) {
return std::string();
}
std::string result;
result.reserve(strlen(str));
for (const char* p = str; *p; ++p) {
switch (*p) {
case '"':
result.append("&quot;");
break;
case '&':
result.append("&amp;");
break;
case '<':
result.append("&lt;");
break;
case '>':
result.append("&gt;");
break;
case '\'':
result.append("&apos;");
break;
default:
result.push_back(*p);
break;
}
}
return result;
}
} // namespace
void Gui::SoFCDB::writeX3DFields(
SoNode* node,
std::map<SoNode*, std::string>& nodeMap,
@@ -522,7 +559,8 @@ void Gui::SoFCDB::writeX3DFields(
}
nodeMap[node] = str.str();
out << " DEF=\"" << str.str() << "\"";
std::string escapedName = escapeXmlAttribute(str.str().c_str());
out << " DEF=\"" << escapedName << "\"";
}
const SoFieldData* fielddata = node->getFieldData();
@@ -545,9 +583,12 @@ void Gui::SoFCDB::writeX3DFields(
ba = ba.simplified();
}
// escape XML special characters in attribute value
std::string escapedValue = escapeXmlAttribute(ba.data());
out << '\n'
<< Base::blanks(spaces + 2) << fielddata->getFieldName(i).getString()
<< "=\"" << ba.data() << "\" ";
<< "=\"" << escapedValue << "\" ";
}
else {
numFieldNodes++;
@@ -606,7 +647,8 @@ void Gui::SoFCDB::writeX3DChild(
// remove the VRML prefix from the type name
std::string sftype(node->getTypeId().getName().getString());
sftype = sftype.substr(4);
out << Base::blanks(spaces) << "<" << sftype << " USE=\"" << mapIt->second << "\" />\n";
std::string escapedRef = escapeXmlAttribute(mapIt->second.c_str());
out << Base::blanks(spaces) << "<" << sftype << " USE=\"" << escapedRef << "\" />\n";
}
}