问题有多方面:
例如,请采用以下数据:
<messages>
<m>
<subject>message tagged with A B C</subject>
<tags>A B C</tags>
</m>
<m>
<subject>message tagged with B C D</subject>
<tags>B C D</tags>
</m>
<m>
<subject>message tagged with X Y A</subject>
<tags>X Y A</tags>
</m>
<m>
<subject>message tagged with C X</subject>
<tags>C X</tags>
</m>
<m>
<subject>message tagged with Y</subject>
<tags>Y</tags>
</m>
</messages>
给定一组已知标签,比如说
<xsl:param name="pKnownTags">
<t>A</t>
<t>B</t>
</xsl:param>
我想生成一个看起来像的输出:
Messages tagged with A:
* message tagged with A B C
* message tagged with X Y A
Messages tagged with B:
* message tagged with A B C
* message tagged with B C D
Messages tagged with neither:
* message tagged with C X
* message tagged with Y
使用EXSLT很好,但是否则需要1.0解决方案。这可能吗?
答案 0 :(得分:0)
这不需要任何太花哨的东西。请试试以下内容:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"
>
<xsl:output method="text" indent="yes"/>
<xsl:param name="pKnownTags">
<t>A</t>
<t>B</t>
</xsl:param>
<xsl:variable name="pKnownTagsNodeSet" select="exsl:node-set($pKnownTags)/t" />
<xsl:template match="/messages">
<xsl:apply-templates select="$pKnownTagsNodeSet">
<xsl:with-param name="docEl" select="." />
</xsl:apply-templates>
<xsl:text>Messages tagged with none of the above:
</xsl:text>
<xsl:apply-templates select="m" mode="checkAbsence" />
</xsl:template>
<xsl:template match="t">
<xsl:param name="docEl" select="/.." />
<xsl:value-of select="concat('Messages tagged with ', ., ':
')"/>
<xsl:apply-templates select="$docEl/m[contains(concat(' ', tags, ' '),
concat(' ', current(), ' '))]" />
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="m" mode="checkAbsence">
<xsl:variable name="currentTagsPadded" select="concat(' ', tags, ' ')" />
<xsl:apply-templates
select="(.)[not($pKnownTagsNodeSet[contains($currentTagsPadded,
concat(' ', ., ' '))]
)
]" />
</xsl:template>
<xsl:template match="m">
<xsl:value-of select="concat('* ', subject, '
')"/>
</xsl:template>
</xsl:stylesheet>
在样本输入上运行时,会产生:
Messages tagged with A:
* message tagged with A B C
* message tagged with X Y A
Messages tagged with B:
* message tagged with A B C
* message tagged with B C D
Messages tagged with none of the above:
* message tagged with C X
* message tagged with Y
答案 1 :(得分:0)
使用EXSLT很好
好吧,如果您的处理器支持EXSLT str:tokenize()函数,那么这可能非常简单:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="exsl str">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:param name="pKnownTags">
<t>A</t>
<t>B</t>
</xsl:param>
<xsl:variable name="tags-set" select="exsl:node-set($pKnownTags)/t" />
<xsl:variable name="xml" select="/" />
<xsl:key name="message-by-tags" match="m" use="str:tokenize(tags)" />
<xsl:template match="/">
<!-- matching messages -->
<xsl:for-each select="$tags-set">
<xsl:variable name="tag" select="." />
<xsl:value-of select="concat('Messages tagged with ', $tag, ': ')"/>
<!-- switch context to source document in order to use key -->
<xsl:for-each select="$xml">
<xsl:for-each select="key('message-by-tags', $tag)">
<xsl:value-of select="concat('* ', subject, ': ')"/>
</xsl:for-each>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:for-each>
<!-- non-matching messages -->
<xsl:text>Messages tagged with none: </xsl:text>
<xsl:for-each select="messages/m[not(str:tokenize(tags)=$tags-set)]">
<xsl:value-of select="concat('* ', subject)"/>
<xsl:if test="position()!=last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>