我有一个 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吗?
答案 0 :(得分:3)
我会使用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 :(得分:1)
因为正则表达式通过单次传递非常糟糕,而且我假设强调的“1次”意味着一次性的努力 - 而不是它必须一举发生(或只有一个表达式) ,我建议两个阶段(我正在使用Perl语法)
第一阶段(将外部标签更改为新标签容器名称):
s!<(/?)items>!<$1itemList>!
第二阶段(解析列出的项目,如果它们在容器中):
s!,([^<,]+)(?=,|</itemList>)|(?<=<itemList>)([^<,]+)(?=,|</itemList>)!\n <item>$1$2</item>!
这些表达式将生成您需要的内容,但可能无法完全生成您在示例输出中显示的空格。这也假设标签就像你的问题一样简单...如果你变得更复杂(许多不同的名字等等),你应该看看XSLT
如果你想以与示例输出相同的方式对其进行格式化,请在第三次传递时使用最后一个表达式,这将在正确的位置添加额外的回车符:
s!(</item>)(</itemList>)!$1\n$2!