拆分逗号值以分隔 nodes/elements XSLT
Split Comma Value to Separate nodes/elements XSLT
我有一个场景,在 XML 字段之一中,源应用程序正在发送逗号分隔值(根据它们的限制),但我们的目标系统只接受字段中的单个值(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>
如果您使用的系统只有 xmlstarlet - which relies on libxslt and therefore supports xslt-1.0 and 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>
我有一个场景,在 XML 字段之一中,源应用程序正在发送逗号分隔值(根据它们的限制),但我们的目标系统只接受字段中的单个值(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>
如果您使用的系统只有 xmlstarlet - which relies on libxslt and therefore supports xslt-1.0 and 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>