XSL:获取在单独节点中包含任何单词的文本值



如果文本包含<vehicleType><color>中的任何单词,我正在尝试获取<line>中的文本。我还需要计算<vehicleType><color>中有多少单词包含在<description>.是否可以使用 XSL(版本=1.0)?

输出应如下所示:

Vehicle type (4)
This vehicle is a white <font color="red">compact car</font>.
This vehicle is a orange <font color="red">minivan</font>.
This vehicle is a red <font color="red">sedan</font>.
This vehicle is a yellow <font color="red">truck</font>.
Color (4)
This vehicle is a <font color="red">white</font> compact car.
This vehicle is a <font color="red">red</font> sedan.
This vehicle is a <font color="red">yellow</font> truck.
This vehicle is a <font color="red">yellow</font> crossover.

以下是简化的 xml:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test9.xsl"?>
<items>
<vehicleTypes>
<vehicleType>truck</vehicleType>
<vehicleType>compace</vehicleType>
<vehicleType>car</vehicleType>
<vehicleType>sedan</vehicleType>
<vehicleType>minivan</vehicleType>
</vehicleTypes>
<colors>
<color>red</color>
<color>yellow</color>
<color>blue</color>
<color>white</color>
<color>purple</color>
<color>gold</color>
<color>silver</color>
</colors>
<item>
<description>
<p>
<line>
This vehicle is a white compact car.
</line>
<line>
This vehicle is a orange minivan.
</line>
<line>
This vehicle is a red sedan.
</line>
<line>
This vehicle is a yellow truck.
</line>
<line>
This vehicle is a yellow crossover.
</line>
</p>
</description>
</item>
</items>

为了测试"vehicleType"或"color"中的任何逗号分隔值是否作为空格或标点符号分隔的单词或短语出现在当前元素中,我会写这样的东西(未经测试):

<xsl:variable name="needles.vT" as="xs:string"
select="tokenize(/items/vehicleType,',')"/>
<xsl:variable name="needles.c" as="xs:string"
select="tokenize(/items/color,',')"/>
<xsl:variable name="haystack" as="xs:string"
select="concat(' ',
normalize-space(
translate(.,
' .,;:!?()-=+',
'            '),
' ')"/>
<xsl:if test="some $needle in ($needles.vT, $needles.c)
satisfies contains($haystack, 
concat(' ', $needle, ' ')">
... code for magic-word-found case ...
</xsl:if>

可能还有更优雅的方法可以做到这一点。

为了计算大海捞针中的车辆类型和颜色针的数量,我会使用类似的东西

count($needles.vT[contains($haystack, concat(' ', ., ' '))])
count($needles.c[contains($haystack, concat(' ', ., ' '))])

在 XSLT 1.0 中,我会编写一个递归模板,该模板通过术语列表工作,剥离第一个术语,如果匹配,则向累加器添加一个术语,并在术语列表的其余部分重复出现。 一般形式是

<xsl:template name="countHits">
<xsl:param name="needles"/><!--* terms to seek *-->
<xsl:param name="haystack"/><!--* where to seek them *-->
<xsl:param name="accumulator" select="0"/>
<!--* number of hits so far *-->
<xsl:variable name="needle">
<xsl:choose>
<xsl:when test="contains($needles, ',')">
<xsl:value-of select="substring-before($needles, ',')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$needles"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="normalize-space($needles) = ''">
<xsl:value-of select="$accumulator"/>
</xsl:when>
<xsl:when test="contains($haystack, concat(' ', $needle, ' ')">
<xsl:call-template name="countHits">
<xsl:with-param name="needles"
select="substring-after($needles, ',')"/>
<xsl:with-param name="haystack"
select="$haystack"/>
<xsl:with-param name="accumulator"
select="1 + $accumulator"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="countHits">
<xsl:with-param name="needles"
select="substring-after($needles, ',')"/>
<xsl:with-param name="haystack"
select="$haystack"/>
<xsl:with-param name="accumulator"
select="$accumulator"/>
</xsl:call-template>
</xsl:otherwise>        
</xsl:choose>
</xsl:template>

我假设您可以弄清楚如何准备$haystack的初始值以及如何调用模板。

如果您对 XML 的形式有任何控制,则可以考虑更改"车辆类型"和"颜色"以将单独的值放在单独的元素中,因此:

<colors>
<color>red</color>
<color>yellow</color>
<color>blue</color>
<color>white</color>
<color>purple</color>
<color>gold</color>
<color>silver</color>
</colors>

然后测试变为如下所示($haystack定义如上):

<xsl:variable name="colorcount"
select="count(/items/colors/color
[contains($haystack, concat(' ', ., ' ')])"/>

车辆类型也是如此。

最新更新