Поскольку регулярные выражения довольно плохо выполняют именно это за один проход, и я предполагаю, что подчеркнутое «1 раз» означает одноразовое усилие, а не то, что это должно произойти одним махом (или только одним выражением) Я бы порекомендовал два этапа (и я использую синтаксис Perl)
первый этап (измените внешние теги на имя нового контейнера тегов):
s!<(/?)items>!<$1itemList>!
второй этап (парсинг перечисленных предметов, если они находятся в контейнерах):
s!,([^<,]+)(?=,|</itemList>)|(?<=<itemList>)([^<,]+)(?=,|</itemList>)!\n <item>$1$2</item>!
Эти выражения будут производить то, что вам нужно, но могут не производить ТОЧНО пробел, который вы показали в своем примере вывода. Это также предполагает, что теги так же просты, как показывает ваш вопрос ... если вы усложняете задачу (много разных имен и т. Д.), Вам, вероятно, стоит взглянуть на XSLT
Если вы хотите, чтобы он был отформатирован так же, как в вашем примере вывода, используйте это последнее выражение на третьем проходе, которое добавит дополнительный возврат каретки в нужное место:
s!(</item>)(</itemList>)!$1\n$2!