diff --git a/src/db/plugins/upnp/Directory.hxx b/src/db/plugins/upnp/Directory.hxx
index b8c591171..cb458e542 100644
--- a/src/db/plugins/upnp/Directory.hxx
+++ b/src/db/plugins/upnp/Directory.hxx
@@ -40,7 +40,7 @@ public:
 	~UPnPDirContent();
 
 	gcc_pure
-	UPnPDirObject *FindObject(const char *name) noexcept {
+	UPnPDirObject *FindObject(std::string_view name) noexcept {
 		for (auto &o : objects)
 			if (o.name == name)
 				return &o;
diff --git a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx
index 9c030161a..ac6240893 100644
--- a/src/db/plugins/upnp/UpnpDatabasePlugin.cxx
+++ b/src/db/plugins/upnp/UpnpDatabasePlugin.cxx
@@ -106,7 +106,7 @@ public:
 
 private:
 	void VisitServer(const ContentDirectoryService &server,
-			 std::forward_list<std::string> &&vpath,
+			 std::forward_list<std::string_view> &&vpath,
 			 const DatabaseSelection &selection,
 			 const VisitDirectory& visit_directory,
 			 const VisitSong& visit_song,
@@ -126,7 +126,7 @@ private:
 				   const DatabaseSelection &selection) const;
 
 	UPnPDirObject Namei(const ContentDirectoryService &server,
-			    std::forward_list<std::string> &&vpath) const;
+			    std::forward_list<std::string_view> &&vpath) const;
 
 	/**
 	 * Take server and objid, return metadata.
@@ -192,7 +192,7 @@ UpnpDatabase::GetSong(const char *uri) const
 		throw DatabaseError(DatabaseErrorCode::NOT_FOUND,
 				    "No such song");
 
-	auto server = discovery->GetServer(vpath.front().c_str());
+	auto server = discovery->GetServer(vpath.front());
 	vpath.pop_front();
 
 	if (vpath.empty())
@@ -208,7 +208,7 @@ UpnpDatabase::GetSong(const char *uri) const
 			throw DatabaseError(DatabaseErrorCode::NOT_FOUND,
 					    "No such song");
 
-		dirent = ReadNode(server, vpath.front().c_str());
+		dirent = ReadNode(server, std::string(vpath.front()).c_str());
 	}
 
 	return new UpnpSong(std::move(dirent), uri);
@@ -407,7 +407,7 @@ UpnpDatabase::BuildPath(const ContentDirectoryService &server,
 // Take server and internal title pathname and return objid and metadata.
 UPnPDirObject
 UpnpDatabase::Namei(const ContentDirectoryService &server,
-		    std::forward_list<std::string> &&vpath) const
+		    std::forward_list<std::string_view> &&vpath) const
 {
 	if (vpath.empty())
 		// looking for root info
@@ -420,7 +420,7 @@ UpnpDatabase::Namei(const ContentDirectoryService &server,
 		auto dirbuf = server.readDir(handle, objid.c_str());
 
 		// Look for the name in the sub-container list
-		UPnPDirObject *child = dirbuf.FindObject(vpath.front().c_str());
+		UPnPDirObject *child = dirbuf.FindObject(vpath.front());
 		if (child == nullptr)
 			throw DatabaseError(DatabaseErrorCode::NOT_FOUND,
 					    "No such object");
@@ -495,7 +495,7 @@ VisitObject(const UPnPDirObject &object, const char *uri,
 // really just one path parameter.
 void
 UpnpDatabase::VisitServer(const ContentDirectoryService &server,
-			  std::forward_list<std::string> &&vpath,
+			  std::forward_list<std::string_view> &&vpath,
 			  const DatabaseSelection &selection,
 			  const VisitDirectory& visit_directory,
 			  const VisitSong& visit_song,
@@ -514,7 +514,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
 		if (vpath.empty())
 			return;
 
-		const std::string objid(std::move(vpath.front()));
+		const std::string objid(vpath.front());
 		vpath.pop_front();
 		if (!vpath.empty())
 			throw DatabaseError(DatabaseErrorCode::NOT_FOUND,
@@ -611,7 +611,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
 	}
 
 	// We do have a path: the first element selects the server
-	std::string servername(std::move(vpath.front()));
+	std::string servername(vpath.front());
 	vpath.pop_front();
 
 	auto server = discovery->GetServer(servername.c_str());
diff --git a/src/lib/upnp/ContentDirectoryService.cxx b/src/lib/upnp/ContentDirectoryService.cxx
index fa8eaace3..4c80820e6 100644
--- a/src/lib/upnp/ContentDirectoryService.cxx
+++ b/src/lib/upnp/ContentDirectoryService.cxx
@@ -23,7 +23,7 @@
 #include "ixmlwrap.hxx"
 #include "util/UriRelative.hxx"
 #include "util/RuntimeError.hxx"
-#include "util/SplitString.hxx"
+#include "util/IterableSplitString.hxx"
 
 #include <upnptools.h>
 
@@ -73,5 +73,8 @@ ContentDirectoryService::getSearchCapabilities(UpnpClient_Handle hdl) const
 		   understand that */
 		return std::forward_list<std::string>();
 
-	return SplitString(s, ',', false);
+	std::forward_list<std::string> result;
+	for (const auto &i : IterableSplitString(s, ','))
+		result.emplace_front(i);
+	return result;
 }
diff --git a/src/lib/upnp/Discovery.cxx b/src/lib/upnp/Discovery.cxx
index f8339364b..3cd1b4b07 100644
--- a/src/lib/upnp/Discovery.cxx
+++ b/src/lib/upnp/Discovery.cxx
@@ -325,7 +325,7 @@ UPnPDeviceDirectory::GetDirectories()
 }
 
 ContentDirectoryService
-UPnPDeviceDirectory::GetServer(const char *friendly_name)
+UPnPDeviceDirectory::GetServer(std::string_view friendly_name)
 {
 	const std::lock_guard<Mutex> protect(mutex);
 
diff --git a/src/lib/upnp/Discovery.hxx b/src/lib/upnp/Discovery.hxx
index 9673bd536..f284916ee 100644
--- a/src/lib/upnp/Discovery.hxx
+++ b/src/lib/upnp/Discovery.hxx
@@ -176,7 +176,7 @@ public:
 	/**
 	 * Get server by friendly name.
 	 */
-	ContentDirectoryService GetServer(const char *friendly_name);
+	ContentDirectoryService GetServer(std::string_view friendly_name);
 
 private:
 	void Search();
diff --git a/src/tag/Config.cxx b/src/tag/Config.cxx
index eb608aeb1..7fada6cfa 100644
--- a/src/tag/Config.cxx
+++ b/src/tag/Config.cxx
@@ -25,6 +25,7 @@
 #include "util/ASCII.hxx"
 #include "util/RuntimeError.hxx"
 #include "util/SplitString.hxx"
+#include "util/StringView.hxx"
 
 void
 TagLoadConfig(const ConfigData &config)
@@ -44,15 +45,11 @@ TagLoadConfig(const ConfigData &config)
 		/* no "+-": not incremental */
 		global_tag_mask = TagMask::None();
 
-	for (const auto &i : SplitString(value, ',')) {
-		const char *name = i.c_str();
-
-		if (*name == '+') {
+	for (StringView name : SplitString(value, ',')) {
+		if (name.SkipPrefix("+")) {
 			plus = true;
-			++name;
-		} else if (*name == '-') {
+		} else if (name.SkipPrefix("-")) {
 			plus = false;
-			++name;
 		}
 
 		const auto type = tag_name_parse_i(name);
diff --git a/src/util/SplitString.cxx b/src/util/SplitString.cxx
index 5676b098f..821ba1af8 100644
--- a/src/util/SplitString.cxx
+++ b/src/util/SplitString.cxx
@@ -31,28 +31,24 @@
 #include "IterableSplitString.hxx"
 #include "StringStrip.hxx"
 
-std::forward_list<std::string>
+std::forward_list<std::string_view>
 SplitString(std::string_view _s, char separator, bool strip) noexcept
 {
 	StringView s(_s);
 	if (strip)
 		s.StripLeft();
 
-	std::forward_list<std::string> list;
+	std::forward_list<std::string_view> list;
 	if (s.empty())
 		return list;
 
 	auto i = list.before_begin();
 
 	for (auto value : IterableSplitString(s, separator)) {
-		const char *begin = value.begin(), *end = value.end();
+		if (strip)
+			value.Strip();
 
-		if (strip) {
-			begin = StripLeft(begin, end);
-			end = StripRight(begin, end);
-		}
-
-		i = list.emplace_after(i, begin, end);
+		i = list.emplace_after(i, value);
 	}
 
 	return list;
diff --git a/src/util/SplitString.hxx b/src/util/SplitString.hxx
index 7ecc8997e..8e22ee457 100644
--- a/src/util/SplitString.hxx
+++ b/src/util/SplitString.hxx
@@ -31,7 +31,6 @@
 #define SPLIT_STRING_HXX
 
 #include <forward_list>
-#include <string>
 #include <string_view>
 
 /**
@@ -44,7 +43,7 @@
  * An empty input string, as a special case, results in an empty list
  * (and not a list with an empty string).
  */
-std::forward_list<std::string>
+std::forward_list<std::string_view>
 SplitString(std::string_view s, char separator, bool strip=true) noexcept;
 
 #endif