XSLT 根据输入数据的长度动态添加元素
XSLT add elements dynamically on the basis of length of input data
我们有一个输入 XML 消息,其元素中包含编码字符串。要求是我们要根据该字符串的长度创建输出 XML 消息。预期输出元素的长度限制为 10 个字符,并且对该元素可以重复的次数没有限制。
示例:
例如,在下面的消息中,您可以看到我们有一个元素 EncodedString,它包含一个长度为 100 个字符的字符串。在输出中,我们希望 EncodedStringValue 元素出现 10 次,因为每个元素声明的最大限制为 10 个字符。
请注意,在实际情况下,我们可以拥有的字符数限制可能与 10 个不同。
输入XML
<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns="http://ws.apache.org/ns/synapse">
<MessageID>365</MessageID>
<EncodedString>PHJvb3Q6SW52b2ljZSB4bWxuczpyb290PSJ1cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2NoZW1hOnhzZDpJbnZv</EncodedString>
</Message>
预期输出XML
<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns="http://ws.apache.org/ns/synapse">
<MessageID>365</MessageID>
<EncodedStringValue>PHJvb3Q6SW</EncodedStringValue>
<EncodedStringValue>52b2ljZSB4</EncodedStringValue>
<EncodedStringValue>bWxuczpyb2</EncodedStringValue>
<EncodedStringValue>90PSJ1cm46</EncodedStringValue>
<EncodedStringValue>b2FzaXM6bm</EncodedStringValue>
<EncodedStringValue>FtZXM6c3Bl</EncodedStringValue>
<EncodedStringValue>Y2lmaWNhdG</EncodedStringValue>
<EncodedStringValue>lvbjp1Ymw6</EncodedStringValue>
<EncodedStringValue>c2NoZW1hOn</EncodedStringValue>
<EncodedStringValue>hzZDpJbnZv</EncodedStringValue>
</Message>
问题?
是否可以使用XSLT实现上述需求?如果是那么怎么办?
使用字符串函数拆分数据,例如在 XSLT 中使用 analyze-string
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="http://ws.apache.org/ns/synapse"
exclude-result-prefixes="#all"
expand-text="yes"
version="3.0">
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="EncodedString">
<xsl:apply-templates select="analyze-string(., '.{1,10}')/*:match">
<xsl:with-param name="name" select="node-name()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*:match">
<xsl:param name="name"/>
<xsl:element name="{$name}" namespace="{namespace-uri-from-QName($name)}">{.}</xsl:element>
</xsl:template>
</xsl:stylesheet>
在 XSLT 2.0 中同样可以执行如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://ws.apache.org/ns/synapse"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<Message>
<xsl:apply-templates select="node()"/>
</Message>
</xsl:template>
<xsl:template match="MessageID">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:template>
<xsl:template match="EncodedString">
<xsl:variable name="rep">
<xsl:value-of select="replace(.,'([0-9A-z]{1,10})',' ')"/>
</xsl:variable>
<xsl:for-each select="tokenize($rep,' ')[position()!=last()]">
<EncodedStringValue>
<xsl:value-of select="."/>
</EncodedStringValue>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我们有一个输入 XML 消息,其元素中包含编码字符串。要求是我们要根据该字符串的长度创建输出 XML 消息。预期输出元素的长度限制为 10 个字符,并且对该元素可以重复的次数没有限制。
示例:
例如,在下面的消息中,您可以看到我们有一个元素 EncodedString,它包含一个长度为 100 个字符的字符串。在输出中,我们希望 EncodedStringValue 元素出现 10 次,因为每个元素声明的最大限制为 10 个字符。 请注意,在实际情况下,我们可以拥有的字符数限制可能与 10 个不同。
输入XML
<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns="http://ws.apache.org/ns/synapse">
<MessageID>365</MessageID>
<EncodedString>PHJvb3Q6SW52b2ljZSB4bWxuczpyb290PSJ1cm46b2FzaXM6bmFtZXM6c3BlY2lmaWNhdGlvbjp1Ymw6c2NoZW1hOnhzZDpJbnZv</EncodedString>
</Message>
预期输出XML
<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns="http://ws.apache.org/ns/synapse">
<MessageID>365</MessageID>
<EncodedStringValue>PHJvb3Q6SW</EncodedStringValue>
<EncodedStringValue>52b2ljZSB4</EncodedStringValue>
<EncodedStringValue>bWxuczpyb2</EncodedStringValue>
<EncodedStringValue>90PSJ1cm46</EncodedStringValue>
<EncodedStringValue>b2FzaXM6bm</EncodedStringValue>
<EncodedStringValue>FtZXM6c3Bl</EncodedStringValue>
<EncodedStringValue>Y2lmaWNhdG</EncodedStringValue>
<EncodedStringValue>lvbjp1Ymw6</EncodedStringValue>
<EncodedStringValue>c2NoZW1hOn</EncodedStringValue>
<EncodedStringValue>hzZDpJbnZv</EncodedStringValue>
</Message>
问题?
是否可以使用XSLT实现上述需求?如果是那么怎么办?
使用字符串函数拆分数据,例如在 XSLT 中使用 analyze-string
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="http://ws.apache.org/ns/synapse"
exclude-result-prefixes="#all"
expand-text="yes"
version="3.0">
<xsl:output indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="EncodedString">
<xsl:apply-templates select="analyze-string(., '.{1,10}')/*:match">
<xsl:with-param name="name" select="node-name()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*:match">
<xsl:param name="name"/>
<xsl:element name="{$name}" namespace="{namespace-uri-from-QName($name)}">{.}</xsl:element>
</xsl:template>
</xsl:stylesheet>
在 XSLT 2.0 中同样可以执行如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://ws.apache.org/ns/synapse"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<Message>
<xsl:apply-templates select="node()"/>
</Message>
</xsl:template>
<xsl:template match="MessageID">
<xsl:copy-of select="."></xsl:copy-of>
</xsl:template>
<xsl:template match="EncodedString">
<xsl:variable name="rep">
<xsl:value-of select="replace(.,'([0-9A-z]{1,10})',' ')"/>
</xsl:variable>
<xsl:for-each select="tokenize($rep,' ')[position()!=last()]">
<EncodedStringValue>
<xsl:value-of select="."/>
</EncodedStringValue>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>