Как преобразовать узел XML с запятыми на несколько узлов? - PullRequest
2 голосов
/ 19 сентября 2011

У меня есть преобразование 1 раз для большого XML-файла.

У меня есть:

[stuff]
<items>string1,string2,string3,string4</items>
[other stuff]

Я хочу заменить его на:

<itemList>
    <item>string1</item>
    <item>string2</item>
    <item>string3</item>
    <item>string4</item>
</itemList>

Я колеблюсь между использованием RegEx или XSL.Я пытался пойти по пути регулярных выражений:

Поиск

^.*<items>(.*)</items>

Заменить на

<itemList>\1</itemList>

Я застрял на "найти запятую и заменить ихчем-то ".Я даже не уверен, что это выполнимо ...

Как я могу закончить этот RegEx?Должен ли я пойти XSL вместо этого?

Ответы [ 2 ]

3 голосов
/ 20 сентября 2011

Я бы использовал XSLT 2.0.

Ввод XML:

<doc>
  <stuff>sdfsadfsa</stuff>
  <items>string,string,string,string</items>
  <otherstuff>sdfasdfsaf</otherstuff>
</doc>

XSLT 2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="items">
    <itemList>
      <xsl:for-each select="tokenize(.,',')">
        <item><xsl:value-of select="."/></item>
      </xsl:for-each>
    </itemList>
  </xsl:template>

</xsl:stylesheet>

Вывод XML:

<doc>
   <stuff>sdfsadfsa</stuff>
   <itemList>
      <item>string</item>
      <item>string</item>
      <item>string</item>
      <item>string</item>
   </itemList>
   <otherstuff>sdfasdfsaf</otherstuff>
</doc>

Если у вас нет процессора XSLT 2.0, я бы предложил Saxon .

1 голос
/ 20 сентября 2011

Поскольку регулярные выражения довольно плохо выполняют именно это за один проход, и я предполагаю, что подчеркнутое «1 раз» означает одноразовое усилие, а не то, что это должно произойти одним махом (или только одним выражением) Я бы порекомендовал два этапа (и я использую синтаксис Perl)

первый этап (измените внешние теги на имя нового контейнера тегов):

s!<(/?)items>!<$1itemList>!

второй этап (парсинг перечисленных предметов, если они находятся в контейнерах):

s!,([^<,]+)(?=,|</itemList>)|(?<=<itemList>)([^<,]+)(?=,|</itemList>)!\n    <item>$1$2</item>!

Эти выражения будут производить то, что вам нужно, но могут не производить ТОЧНО пробел, который вы показали в своем примере вывода. Это также предполагает, что теги так же просты, как показывает ваш вопрос ... если вы усложняете задачу (много разных имен и т. Д.), Вам, вероятно, стоит взглянуть на XSLT

Если вы хотите, чтобы он был отформатирован так же, как в вашем примере вывода, используйте это последнее выражение на третьем проходе, которое добавит дополнительный возврат каретки в нужное место:

s!(</item>)(</itemList>)!$1\n$2!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...