我需要帮助,请根据XML的字符长度和因素分析XML中的源数据是否在单词的中间以及是否有逗号。 EG:我的传递地址行长度不能超过35个字符(这包括任何空格,逗号等,理想情况下我想分割地址以确保我想输出的2个地址行不超过35个字符,如果我根据这个最大限制来分割源数据,我是在逗号点或者在一个单词的结尾处这样做,然后将剩余的数据附加到下一行,所以关于不丢失客户提供的任何数据(可避免的地方)。
我目前正在使用 XSLT版本1 ,但如果需要,可以支持使用版本2.
这是我的源数据,我一直在尝试做什么以及我想要的输出是什么。仅供参考我的输出采用管道分隔格式。
XML
<AddressData>
<Delivery>
<ConsigneeAddress>Rosedal 67, departamento 3A, Lomasde Chapultepec, Miguel hidalgo</ConsigneeAddress>
<ConsigneeAddress2/>
</Delivery>
<Delivery>
<ConsigneeAddress>Str.Codreanu,30, Chisinau, MD-200018,</ConsigneeAddress>
<ConsigneeAddress2>Moldova, Republic of</ConsigneeAddress2>
</Delivery>
</AddressData>
XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/">
<xsl:for-each select="/AddressData/Delivery">
<xsl:choose>
<xsl:when test="string-length(./ConsigneeAddress) > 35">
<xsl:value-of select="substring-before(./ConsigneeAddress,',')"/><xsl:text>, </xsl:text><xsl:value-of select="substring-before(substring-after(./ConsigneeAddress,','),',')"/>
<xsl:if test="./ConsigneeAddress2=''">
<xsl:text>|</xsl:text>
<xsl:value-of select="normalize-space(substring-before(substring-after(substring-after(./ConsigneeAddress,','),','),./ConsigneeZipCode))"/>
</xsl:if>
<xsl:if test="./ConsigneeAddress2!=''">
<xsl:text>|</xsl:text>
<xsl:value-of select="normalize-space(./ConsigneeAddress2)"/><xsl:text>, </xsl:text><xsl:value-of select="normalize-space(substring-after(substring-after(./ConsigneeAddress,','),','))"/>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="./ConsigneeAddress"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="./ConsigneeAddress2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
期望的输出:
Rosedal 67,departamento 3A | Lomasde Chapultepec,Miguel hidalgo
Str.Codreanu,30岁,基希讷乌,| MD-200018,摩尔多瓦共和国
任何帮助/帮助将不胜感激。提前谢谢。
答案 0 :(得分:0)
您可以更改为 XSLT 2 ,因为tt具有更强大的功能。
其中一个对您来说很有用analyze-string
。
您可以使用以下脚本:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each select="/AddressData/Delivery">
<xsl:apply-templates select="ConsigneeAddress"/>
<xsl:if test="position() < last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="ConsigneeAddress">
<xsl:analyze-string select="."
regex="(\w.{{0,33}}\w)(,\s*|$)">
<xsl:matching-substring>
<xsl:value-of select="regex-group(1)"/>
<xsl:if test="position() < last()">
<xsl:text>|</xsl:text>
</xsl:if>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:transform>
关于正则表达式的解释:
要匹配的每个子字符串:
\w
)开头。{
和}
但是这里(由于XSLT语法)它们必须加倍。以上所有项目(总共最多35个字符)构成第一个捕获组。
之后还有另一组包含2个变种:
它们也应该在这里“消耗”以便开始下一次搜索 在他们之后。
从这两组我们实际上只对第一组感兴趣,
所以在XSLT脚本value-of
语句中只打印出来
第一组(regex-group(1)
)。
打印出捕获的组后,脚本会打印出|
,
但只是“在序列的中间”(即不是在最后一个之后)
匹配的字符串)。
主模板还会在每个 ConsigneeAddress 之后打印换行符 但最后一次。