以字符开头和后跟字符的XSLT过滤



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

<?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>

测试启动条件我增加了三项检查。contains检查在空字符串情况下返回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过滤任务,其中开始和连续字符是有条件的?

编辑阅读迈克尔。Hor257k的评论让我对自己的做法产生了质疑,也让我更加了解自己的需求。有一个Cybersource页面,它在向api发出请求时指定允许的字符。我的目标是清理不需要的字符,并确保该领域开始,然后是字符符合网站上给出的规格。以船到公司名称为例。我使用XSLT 1.0和java Transformer类

考虑以下简化的例子:

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>