根据长度和逗号拆分输入字符串(送货地址数据)

Posted

技术标签:

【中文标题】根据长度和逗号拆分输入字符串(送货地址数据)【英文标题】:Splitting input string (delivery address data) based on length and commas 【发布时间】:2018-03-14 14:50:22 【问题描述】:

我需要帮助,请根据它的字符长度以及它是否在单词中间以及是否有任何逗号来拆分 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,米格尔伊达尔戈 Str.Codreanu,30, 基希讷乌,|MD-200018, 摩尔多瓦, ***

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

【问题讨论】:

请您编辑您的问题,以将源 XML 和 XSLT 包含为代码(可以轻松复制并粘贴到 XML 工具中,例如 xsltransform.net)而不是图像。谢谢。 当然,我可以尝试再次添加代码。当我在发布帖子之前这样做时,格式看起来不正确,就像我读过的其他帖子一样,它保留了所使用的编辑器(例如 XMLSpy)的格式和颜色,但我无法复制这一点。又来了: 来源:&lt;AddressData&gt;&lt;Delivery&gt;&lt;ConsigneeAddress&gt;Rosedal 67, departamento 3A, Lomasde Chapultepec, Miguel hidalgo&lt;/ConsigneeAddress&gt;&lt;ConsigneeAddress2&gt;&lt;/ConsigneeAddress2&gt;&lt;/Delivery&gt;&lt;/Delivery&gt;&lt;Delivery&gt;&lt;ConsigneeAddress&gt;Str.Codreanu,30, Chisinau, MD-200018,&lt;/ConsigneeAddress&gt;&lt;ConsigneeAddress2&gt;Moldova, Republic of&lt;/ConsigneeAddress2&gt;&lt;/Delivery&gt;@98765433334 XSLT:我尝试添加 XSLT,但收到超过最大字符数的错误,因此我已将文件上传到 Google Drive 并为其创建了链接:@ 987654322@ 我已将 XML 和 XSLT 添加到您的问题中。 【参考方案1】:

您可以更改为 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 个任意字符。 请注意,“普通”正则表达式将具有 single 但在这里(由于 XSLT 语法)它们必须加倍。 要捕获的最后一个字符又是一个单词字符。

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

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

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

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

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

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

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

【讨论】:

嗨 Valdi_Bo,感谢您的所有帮助,我可以看到这个工作,但是当我尝试将其合并到我的模板中时,我很难让它工作,我提供了 2 个超链接再次到 XML 和模板(它有我最初删除的其他字段)。第 36 行,我在其中添加了一条评论,是 2 条地址行需要去的地方,在过去的 2 个小时里,我一直在为此烦恼。源 XML:drive.google.com/open?id=0B4ry3wqoFp1VVnVjZlE3R3dzMnM 转换:drive.google.com/open?id=0B4ry3wqoFp1VSnpJRjNCaC1pcmc 谢谢。 提前致歉,我知道这与我发布的内容不同,但我删除了数据以使其看起来更简单,因此我实际上无法让您的解决方案现在在我的模板中工作, 下次我不会这样做了,照原样提供数据。 我错过了在您的示例中,您在 text 模式下使用了 output。现在我也改变了模式和整个解决方案。 您好,不仅仅是输出方式不同,两个文件(Source 和 Transform)的内容也不同。最后,在拆分地址行时,它不能将它们输出到超过 2 行,这也包括 中是否有值。如果 大于 35,那么您会将其余部分附加到输出中的 line2 中,并且 中的任何内容都会添加到它的末尾,即使 line2 的输出总长度超过 35字符,这很好,因为系统将忽略结束字符。 最终,我希望我们能够接受 3 行地址,因此代码将在 XSLT 中更改为输出 3 行地址,每行由管道分隔,和上面的逻辑一样。

以上是关于根据长度和逗号拆分输入字符串(送货地址数据)的主要内容,如果未能解决你的问题,请参考以下文章

mysql中怎么实现对含有逗号的字符串进行以

SQL拆分逗号分隔的字符串

SQL拆分逗号分隔的字符串

在 SSMS 中,我需要拆分多个列,根据逗号分隔保持数据有序

用逗号分割长度未知但子字符串格式已知的 Fortran 字符串?

在换行符和逗号上拆分字符串[重复]