将逗号值拆分为分隔节点/元素XSLT



我有一个场景,在其中一个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="'&#10;'"/>
<xsl:for-each select="order">
<xsl:variable select="id" name="nid"/>
<xsl:for-each select="str:tokenize(value,&quot;,&quot;)">
<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="'&#10;'"/>
</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()&gt;1]">
<xsl:value-of select="'&#10;'"/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

最新更新