【问题标题】:XSLT filitering for both begin with and followed by charactersXSLT 过滤以字符开头和后跟字符
【发布时间】:2021-12-06 22:05:47
【问题描述】:

我在一个项目中工作,我得到了一个允许的字符列表,并且需要删除不需要的字符。我已经完成了以下操作,但是我觉得它很麻烦,而且应该是这样的

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="follow">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ?abcdefghijklmnopqrstuvwxyz-&apos;.,/@&amp;()!+</xsl:variable>
    <xsl:variable name="start">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ?abcdefghijklmnopqrstuvwxyz</xsl:variable>
    <xsl:template match="/">
        <html>
            <body>
                <xsl:choose>
                    <xsl:when test="contains($start, substring(normalize-space(/Author/Name/FirstName),1,1)) and 
                    string-length(substring(normalize-space(/Author/Name/FirstName),1,1)) > 0 and
                    string-length(translate(substring(normalize-space(/Author/Name/FirstName),2),translate(substring(normalize-space(/Author/Name/FirstName),2),$follow,''),'')) &gt; 0">
                        <div>
                            <xsl:value-of select="translate(substring(normalize-space(/Author/Name/FirstName),1),
                            translate(substring(normalize-space(/Author/Name/FirstName),1),$follow,''),'')" />
                        </div>    
                    </xsl:when>
                    <xsl:otherwise>NULL</xsl:otherwise>
                </xsl:choose>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

测试启动条件我添加了三个检查。对于空字符串情况,包含检查返回 true,因此我添加了字符串长度条件,以便为空字符串情况返回 NULL。

FirstName>?    #</FirstName>//NULL
<FirstName></FirstName>//NULL
<FirstName>   ??</FirstName>//??
<LastName>?t*#</LastName>//?t

我用于测试的 XML 在下面

<?xml version="1.0" encoding="UTF-8"?>
<Author>
    <Name>
        <FirstName>xxx</FirstName>
    </Name>
</Author>

我可能错过了任何边缘情况,我的问题是有没有更好的方法来解决这个 XSLT 过滤任务,其中起始字符和连续字符是有条件的?

编辑 阅读 michael.hor257k 评论让我质疑我的方法并更了解我的要求。有 Cybersource 页面,它在向其 api 发出请求时指定允许的字符。我的目标是清除不需要的字符,并确保字段开头和后面的字符符合网站上给出的规范。以 Ship-To 公司名称为例。 我正在使用带有 java Transformer 类的 XSLT 1.0

【问题讨论】:

  • 您使用哪个 XSLT 处理器,哪个 XSLT 版本? Java 建议您可以将 Saxon 与 XSLT 2 或 3 一起使用,其中正则表达式支持是 XPath 2 的一部分,以及更高版本的函数,如 matchesreplace 和 (XPath 3.1) analyze-string 以及 XSLT(使用 xsl:analyze-string)。即使使用 Xalan,我认为也有 EXSLT 或调用 Java 以使用正则表达式的能力。
  • 您的任务并不完全清楚。您说您“需要删除不需要的字符”。假设第一个字符是非法的,您将其删除。因此,第 2 个字符变为第 1 个字符。那么你也需要测试它是否是一个合法的起始角色,不是吗?依此类推,直到您找到合法的或用完为止。我没有完全遵循您的代码,但它似乎在做其他事情。
  • P.S.我的方法是首先从整个字符串中删除所有不允许排在第一位的字符。然后结果字符串的第一个字符(如果有结果字符串)成为最终字符串的第一个字符。接下来,我们从原始字符串中删除所选起始字符之前的字符,并将其余字符过滤为合法的后续字符。同样,这是如果任务如所述。
  • michael.hor257k,我在我的第一个查询中添加了一个编辑。您提供的场景很有意义。我已经编辑了这个问题。我不知道什么是不允许的。我想使用允许的角色来完成任务。如果你能给我一个关于实际实现的草图,我将不胜感激。

标签: java xml xslt


【解决方案1】:

考虑以下简化示例:

XML

<input>
    <item>alpha</item>
    <item>-alpha</item>
    <item>alp§ha</item>
    <item>---al§pha§</item>
    <item>§al-pha</item>
</input>

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="allowed-start-chars">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="allowed-follow-chars">abcdefghijklmnopqrstuvwxyz-</xsl:variable>

<xsl:template match="/input">
    <output>
        <xsl:apply-templates/>
    </output>
</xsl:template>

<xsl:template match="item">
    <!-- find the first character eligible to be starting character -->
    <xsl:variable name="start-chars" select="translate(., translate(., $allowed-start-chars, ''), '')"/>
    <xsl:variable name="start-char" select="substring($start-chars, 1, 1)"/>
    <!-- get text after the chosen starting character -->
    <xsl:variable name="tail" select="substring-after(., $start-char)"/>
    <result original="{.}">
        <xsl:value-of select="$start-char"/>
        <!-- remove unwanted characters from tail -->
        <xsl:value-of select="translate($tail, translate($tail, $allowed-follow-chars, ''), '')"/>
    </result>
</xsl:template>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <result original="alpha">alpha</result>
   <result original="-alpha">alpha</result>
   <result original="alp§ha">alpha</result>
   <result original="---al§pha§">alpha</result>
   <result original="§al-pha">al-pha</result>
</output>

您可能想要为所有字符都被证明是非法的情况添加一个测试 - 尽管这似乎不太可能。


补充:

如果您只想测试输入是否有效,那么您可以这样做:

<xsl:template match="item">
    <!-- test the first character -->
    <xsl:variable name="valid-start-char" select="contains($allowed-start-chars, substring(., 1, 1))"/>
    <!-- test following characters  -->
    <xsl:variable name="invalid-follow-chars" select="translate(substring(., 2), $allowed-follow-chars, '')"/>
    <result original="{.}">
       <xsl:choose>
        <xsl:when test="$valid-start-char and not($invalid-follow-chars)">
            <xsl:value-of select="."/>
        </xsl:when>
        <xsl:otherwise>NULL</xsl:otherwise>
       </xsl:choose>
    </result>
</xsl:template>

得到:

<?xml version="1.0" encoding="UTF-8"?>
<output>
    <result original="alpha">alpha</result>
    <result original="-alpha">NULL</result>
    <result original="alp§ha">NULL</result>
    <result original="---al§pha§">NULL</result>
    <result original="§al-pha">NULL</result>
</output>

【讨论】:

  • 我是 XSLT 的新手,并试图弄清楚如何使用您提供的应用模板并发送条件值。如果有效,则显示过滤后的输出,如果不是,则对结果元素显示 NULL。与我发布的原始 xslt 类似。
  • 恐怕我没有跟上。如果输入有效,则无需过滤。
  • 如果输入有效我想显示abc,如果无效则我想显示NULL结果>
  • 这与原始任务有很大不同。我已将此添加到我的答案中,但您应该将此作为单独的问题发布。
  • 对造成的混乱表示歉意。你原来的方法是我正在寻找的,但我唯一的问题是当所有字符都被证明是非法的时,它会导致 。我想在您的原始答案中添加选择/何时或某种 xslt 条件,以便当所有字符均非法时,我将返回 NULL。我接受了你的回答
猜你喜欢
  • 1970-01-01
  • 2020-09-04
  • 2021-11-04
  • 2023-02-09
  • 2020-03-08
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
相关资源
最近更新 更多