diff --git a/apps/gdal_translate_lib.cpp b/apps/gdal_translate_lib.cpp
index 3490d8234d87..964dbd1842c2 100644
--- a/apps/gdal_translate_lib.cpp
+++ b/apps/gdal_translate_lib.cpp
@@ -2582,18 +2582,10 @@ static void AttachMetadata(GDALDatasetH hDS,
                            const CPLStringList &aosMetadataOptions)
 
 {
-    const int nCount = aosMetadataOptions.size();
-
-    for (int i = 0; i < nCount; i++)
+    for (const auto &[pszKey, pszValue] :
+         cpl::IterateNameValue(aosMetadataOptions))
     {
-        char *pszKey = nullptr;
-        const char *pszValue =
-            CPLParseNameValue(aosMetadataOptions[i], &pszKey);
-        if (pszKey && pszValue)
-        {
-            GDALSetMetadataItem(hDS, pszKey, pszValue, nullptr);
-        }
-        CPLFree(pszKey);
+        GDALSetMetadataItem(hDS, pszKey, pszValue, nullptr);
     }
 }
 
@@ -2605,9 +2597,7 @@ static void AttachDomainMetadata(GDALDatasetH hDS,
                                  const CPLStringList &aosDomainMetadataOptions)
 
 {
-    const int nCount = aosDomainMetadataOptions.size();
-
-    for (int i = 0; i < nCount; i++)
+    for (const char *pszStr : aosDomainMetadataOptions)
     {
 
         char *pszKey = nullptr;
@@ -2615,7 +2605,7 @@ static void AttachDomainMetadata(GDALDatasetH hDS,
 
         // parse the DOMAIN:KEY=value, Remainder is KEY=value
         const char *pszRemainder =
-            CPLParseNameValueSep(aosDomainMetadataOptions[i], &pszDomain, ':');
+            CPLParseNameValueSep(pszStr, &pszDomain, ':');
 
         if (pszDomain && pszRemainder)
         {
diff --git a/apps/gdalmdiminfo_lib.cpp b/apps/gdalmdiminfo_lib.cpp
index ad9e1a05ae4b..849d18161101 100644
--- a/apps/gdalmdiminfo_lib.cpp
+++ b/apps/gdalmdiminfo_lib.cpp
@@ -715,21 +715,20 @@ static void DumpStructuralInfo(CSLConstList papszStructuralInfo,
                                CPLJSonStreamingWriter &serializer)
 {
     auto objectContext(serializer.MakeObjectContext());
-    for (int i = 0; papszStructuralInfo && papszStructuralInfo[i]; ++i)
+    int i = 1;
+    for (const auto &[pszKey, pszValue] : cpl::IterateNameValue(
+             papszStructuralInfo, /* bReturnNullKeyIfNotNameValue = */ true))
     {
-        char *pszKey = nullptr;
-        const char *pszValue =
-            CPLParseNameValue(papszStructuralInfo[i], &pszKey);
         if (pszKey)
         {
             serializer.AddObjKey(pszKey);
         }
         else
         {
-            serializer.AddObjKey(CPLSPrintf("metadata_%d", i + 1));
+            serializer.AddObjKey(CPLSPrintf("metadata_%d", i));
+            ++i;
         }
         serializer.Add(pszValue);
-        CPLFree(pszKey);
     }
 }
 
diff --git a/apps/gdaltindex_lib.cpp b/apps/gdaltindex_lib.cpp
index 5c86974f8d47..68c15081642c 100644
--- a/apps/gdaltindex_lib.cpp
+++ b/apps/gdaltindex_lib.cpp
@@ -699,14 +699,11 @@ GDALDatasetH GDALTileIndex(const char *pszDest, int nSrcCount,
         {
             poLayer->SetMetadataItem("MASK_BAND", "YES");
         }
-        for (const auto &osNameValue : psOptions->aosMetadata)
-        {
-            char *pszKey = nullptr;
-            const char *pszValue =
-                CPLParseNameValue(osNameValue.c_str(), &pszKey);
-            if (pszKey && pszValue)
-                poLayer->SetMetadataItem(pszKey, pszValue);
-            CPLFree(pszKey);
+        const CPLStringList aosMetadata(psOptions->aosMetadata);
+        for (const auto &[pszKey, pszValue] :
+             cpl::IterateNameValue(aosMetadata))
+        {
+            poLayer->SetMetadataItem(pszKey, pszValue);
         }
     }
 
diff --git a/apps/gdalwarp_lib.cpp b/apps/gdalwarp_lib.cpp
index a4b5779cf794..4dbec3b5e213 100644
--- a/apps/gdalwarp_lib.cpp
+++ b/apps/gdalwarp_lib.cpp
@@ -266,7 +266,7 @@ static GDALDatasetH GDALWarpCreateOutput(
     GDALWarpAppOptions *psOptions);
 
 static void RemoveConflictingMetadata(GDALMajorObjectH hObj,
-                                      char **papszMetadata,
+                                      CSLConstList papszMetadata,
                                       const char *pszValueConflict);
 
 static bool GetResampleAlg(const char *pszResampling,
@@ -5267,40 +5267,25 @@ static CPLErr TransformCutlineToSource(GDALDataset *poSrcDS,
 }
 
 static void RemoveConflictingMetadata(GDALMajorObjectH hObj,
-                                      char **papszMetadata,
+                                      CSLConstList papszSrcMetadata,
                                       const char *pszValueConflict)
 {
     if (hObj == nullptr)
         return;
 
-    char **papszMetadataRef = CSLDuplicate(papszMetadata);
-    int nCount = CSLCount(papszMetadataRef);
-
-    for (int i = 0; i < nCount; i++)
+    for (const auto &[pszKey, pszValue] :
+         cpl::IterateNameValue(papszSrcMetadata))
     {
-        char *pszKey = nullptr;
-        const char *pszValueRef =
-            CPLParseNameValue(papszMetadataRef[i], &pszKey);
-        if (pszKey != nullptr)
+        const char *pszValueComp = GDALGetMetadataItem(hObj, pszKey, nullptr);
+        if (pszValueComp == nullptr || (!EQUAL(pszValue, pszValueComp) &&
+                                        !EQUAL(pszValueComp, pszValueConflict)))
         {
-            const char *pszValueComp =
-                GDALGetMetadataItem(hObj, pszKey, nullptr);
-            if ((pszValueRef == nullptr || pszValueComp == nullptr ||
-                 !EQUAL(pszValueRef, pszValueComp)) &&
-                (pszValueComp == nullptr ||
-                 !EQUAL(pszValueComp, pszValueConflict)))
-            {
-                if (STARTS_WITH(pszKey, "STATISTICS_"))
-                    GDALSetMetadataItem(hObj, pszKey, nullptr, nullptr);
-                else
-                    GDALSetMetadataItem(hObj, pszKey, pszValueConflict,
-                                        nullptr);
-            }
-            CPLFree(pszKey);
+            if (STARTS_WITH(pszKey, "STATISTICS_"))
+                GDALSetMetadataItem(hObj, pszKey, nullptr, nullptr);
+            else
+                GDALSetMetadataItem(hObj, pszKey, pszValueConflict, nullptr);
         }
     }
-
-    CSLDestroy(papszMetadataRef);
 }
 
 /************************************************************************/
diff --git a/apps/ogrinfo_lib.cpp b/apps/ogrinfo_lib.cpp
index 2cb6e57cb428..193df6b65604 100644
--- a/apps/ogrinfo_lib.cpp
+++ b/apps/ogrinfo_lib.cpp
@@ -645,7 +645,7 @@ GDALVectorInfoPrintMetadata(CPLString &osRet, CPLJSONObject &oMetadata,
     else if (pszDomain != nullptr && STARTS_WITH_CI(pszDomain, "json:"))
         bMDIsJson = true;
 
-    char **papszMetadata = GDALGetMetadata(hObject, pszDomain);
+    CSLConstList papszMetadata = GDALGetMetadata(hObject, pszDomain);
     if (CSLCount(papszMetadata) > 0)
     {
         CPLJSONObject oMetadataDomain;
@@ -1051,33 +1051,27 @@ static void ReportOnLayer(CPLString &osRet, CPLJSONObject &oLayer,
                              oCoordPrec.oFormatSpecificOptions)
                         {
                             CPLJSONObject oThisFormatSpecificOptions;
-                            for (int i = 0; i < formatOptionsPair.second.size();
-                                 ++i)
+                            for (const auto &[pszKey, pszValue] :
+                                 cpl::IterateNameValue(
+                                     formatOptionsPair.second))
                             {
-                                char *pszKey = nullptr;
-                                const char *pszValue = CPLParseNameValue(
-                                    formatOptionsPair.second[i], &pszKey);
-                                if (pszKey && pszValue)
+                                const auto eValueType =
+                                    CPLGetValueType(pszValue);
+                                if (eValueType == CPL_VALUE_INTEGER)
                                 {
-                                    const auto eValueType =
-                                        CPLGetValueType(pszValue);
-                                    if (eValueType == CPL_VALUE_INTEGER)
-                                    {
-                                        oThisFormatSpecificOptions.Add(
-                                            pszKey, CPLAtoGIntBig(pszValue));
-                                    }
-                                    else if (eValueType == CPL_VALUE_REAL)
-                                    {
-                                        oThisFormatSpecificOptions.Add(
-                                            pszKey, CPLAtof(pszValue));
-                                    }
-                                    else
-                                    {
-                                        oThisFormatSpecificOptions.Add(
-                                            pszKey, pszValue);
-                                    }
+                                    oThisFormatSpecificOptions.Add(
+                                        pszKey, CPLAtoGIntBig(pszValue));
+                                }
+                                else if (eValueType == CPL_VALUE_REAL)
+                                {
+                                    oThisFormatSpecificOptions.Add(
+                                        pszKey, CPLAtof(pszValue));
+                                }
+                                else
+                                {
+                                    oThisFormatSpecificOptions.Add(pszKey,
+                                                                   pszValue);
                                 }
-                                CPLFree(pszKey);
                             }
                             oFormatSpecificOptions.Add(
                                 formatOptionsPair.first,