diff --git a/src/libOpenImageIO/xmp.cpp b/src/libOpenImageIO/xmp.cpp
index f919afbfd7..88d630b5cf 100644
--- a/src/libOpenImageIO/xmp.cpp
+++ b/src/libOpenImageIO/xmp.cpp
@@ -408,25 +408,6 @@ add_attrib(ImageSpec& spec, string_view xmlname, string_view xmlvalue,
-// Utility: Search str for the first substring in str (starting from
-// position pos) that starts with startmarker and ends with endmarker.
-// If not found, return false. If found, return true, store the
-// beginning and ending indices in startpos and endpos.
-static bool
-extract_middle(string_view str, size_t pos, string_view startmarker,
- string_view endmarker, size_t& startpos, size_t& endpos)
-{
- startpos = str.find(startmarker, pos);
- if (startpos == std::string::npos)
- return false; // start marker not found
- endpos = str.find(endmarker, startpos);
- if (endpos == std::string::npos)
- return false; // end marker not found
- endpos += endmarker.size();
- return true;
-}
-
-
// Decode one XMP node and its children.
// Return value is the size of the resulting attribute (can be used to
// catch runaway or corrupt XML).
@@ -536,11 +517,30 @@ decode_xmp(string_view xml, ImageSpec& spec)
#endif
if (!xml.length())
return true;
- for (size_t startpos = 0, endpos = 0;
- extract_middle(xml, endpos, "",
- startpos, endpos);) {
- // Turn that middle section into an XML document
- string_view rdf = xml.substr(startpos, endpos - startpos); // scooch in
+ for (size_t pos = 0;;) {
+ // Find the start of the next rdf:Description element
+ size_t startpos = xml.find(" and self-closing />
+ size_t endclose = xml.find("", startpos);
+ size_t endself = xml.find("/>", startpos + 16);
+
+ size_t endpos;
+ if (endclose != std::string::npos) {
+ // Has a closing tag
+ endpos = endclose + 18; // length of ""
+ } else if (endself != std::string::npos) {
+ // Self-closing
+ endpos = endself + 2; // length of "/>"
+ } else {
+ break; // malformed, bail
+ }
+ pos = endpos;
+
+ // Turn that section into an XML document
+ string_view rdf = xml.substr(startpos, endpos - startpos);
#if DEBUG_XMP_READ
std::cerr << "RDF is:\n---\n" << rdf.substr(0, 4096) << "\n---\n";
#endif