我有一个场景,在其中一个XML字段中,Source应用程序正在发送一个逗号分隔的值(根据它们的限制(,但我们的目标系统在一个字段中只接受一个值(不需要id排序(。有人能在这种情况下帮忙吗。提前感谢!
当前XML
<root>
<order>
<id>1</id>
<value>RU</value>
</order>
<order>
<id>2</id>
<value>SA</value>
</order>
<order>
<id>3</id>
<value>MX,BR,US</value>
</order>
<order>
<id>4</id>
<value>IN,SL</value>
</order>
</root>
预期输出:
<root>
<order>
<id>1</id>
<value>RU</value>
</order>
<order>
<id>2</id>
<value>SA</value>
</order>
<order>
<id>3</id>
<value>MX</value>
</order>
<order>
<id>4</id>
<value>IN</value>
</order>
<order>
<id>3</id>
<value>BR</value>
</order>
<order>
<id>3</id>
<value>US</value>
</order>
<order>
<id>4</id>
<value>SL</value>
</order>
</root>
您可以使用tokenize()
函数,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="order[contains(value,',')]">
<xsl:variable name="currentOrder" select="."/>
<xsl:for-each select="tokenize(value,',')">
<order>
<id><xsl:value-of select="$currentOrder/id"/></id>
<value><xsl:value-of select="."/></value>
</order>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
请在此处查看它的工作情况:https://xsltfiddle.liberty-development.net/nbiE19Y
如果您在一个带有xmlstarlet的系统上,它依赖于libxslt,因此只支持xslt-1.0和exslt,您可以说,
xmlstarlet sel
-t -m 'root'
-e '{name()}' -n
-m 'order'
--var nid='id'
-m 'str:tokenize(value,",")'
-e 'order'
-c '$nid'
-e 'value' -v '.' -b
-b -n
file.xml
其中
-t
是与/
匹配的xsl:template
-m
映射到xsl:for-each
-e
就是xsl:element
-c
就是xsl:copy-of
-v
就是xsl:value-of
-b
结束当前容器(-m
.-e
,…(;仅要求如果以下是任何模板选项(在-t
之后(-n
输出换行str:tokenize
是EXSLT工作的一部分- 缩进字符和换行字符是可选的
- 你的
<o/><o/>
型眼睛会得到片刻的放松
输出:
<root>
<order><id>1</id><value>RU</value></order>
<order><id>2</id><value>SA</value></order>
<order><id>3</id><value>MX</value></order>
<order><id>3</id><value>BR</value></order>
<order><id>3</id><value>US</value></order>
<order><id>4</id><value>IN</value></order>
<order><id>4</id><value>SL</value></order>
</root>
要列出生成的XSLT代码,请在-t
选项之前添加-C
:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt str">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="root">
<xsl:element name="{name()}">
<xsl:value-of select="' '"/>
<xsl:for-each select="order">
<xsl:variable select="id" name="nid"/>
<xsl:for-each select="str:tokenize(value,",")">
<xsl:element name="order">
<xsl:copy-of select="$nid"/>
<xsl:element name="value">
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="."/>
</xsl:call-template>
</xsl:element>
</xsl:element>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:template>
<xsl:template name="value-of-template">
<xsl:param name="select"/>
<xsl:value-of select="$select"/>
<xsl:for-each select="exslt:node-set($select)[position()>1]">
<xsl:value-of select="' '"/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>