根据长度和逗号分割输入字符串(传递地址数据)

时间:2017-10-03 11:55:52

标签: xml xslt xpath

我需要帮助,请根据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) &#62; 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,摩尔多瓦共和国


任何帮助/帮助将不胜感激。提前谢谢。

1 个答案:

答案 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() &lt; last()">
        <xsl:text>&#10;</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() &lt; 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)开头。
  • 然后它应包含最多33个任意字符。 请注意,“普通”正则表达式会有单个 {} 但是这里(由于XSLT语法)它们必须加倍。
  • 要捕获的最后一个字符也是一个单词字符。

以上所有项目(总共最多35个字符)构成第一个捕获组。

之后还有另一组包含2个变种:

  • 逗号和一系列“白色”字符,
  • 或字符串的结尾。

它们也应该在这里“消耗”以便开始下一次搜索 在他们之后。

从这两组我们实际上只对第一组感兴趣, 所以在XSLT脚本value-of语句中只打印出来 第一组(regex-group(1))。

打印出捕获的组后,脚本会打印出|, 但只是“在序列的中间”(即不是在最后一个之后) 匹配的字符串)。

主模板还会在每个 ConsigneeAddress 之后打印换行符 但最后一次。