XSLT 检查子字符串是否存在,如果存在则打印

XSLT Check the presence of a substring and then print if exist

考虑以下 XML 输入:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <cd>
    <title>Empire_Burlesque_something</title>
    <title>Empire_Burlesque_other</title>
    <title>Home_Empire_Burlesque</title>
  </cd>
</catalog>

期望的输出是这样的:

Empire: Empire_Burlesque_something;Empire_Burlesque_other;
Home: Home_Empire_Burlesque

显然,这里所做的是,我们从每个输入字符串中选择第一个单词(在第一个“_”之前)并将其标记为 子字符串。然后将针对所有输入字符串检查此子字符串以查看它是否存在,如果存在,则连接所有字符串(如果它们包含该子字符串)并进一步在其前面加上 substring。针对每个输入字符串对所有子字符串重复此过程。

这是我到目前为止所写的内容(是的,它可能会更好、更简单以及所有其他事情,但这是我试图首先获得所需的输出)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="key">
  <xsl:for-each select="catalog/cd/title">
<value>
      <xsl:value-of select="substring-before(current(),'_')" />
</value>
  </xsl:for-each>
</xsl:variable>
<xsl:variable name="abc">
<xsl:for-each select="distinct-values(($key)/value)">
<value>
      <xsl:value-of select="." />
</value>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="value">
  <xsl:for-each select="catalog/cd/title">
    <value>
      <xsl:value-of select="current()" />
    </value>
  </xsl:for-each>
</xsl:variable>
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
<h4><xsl:value-of select="$abc" /></h4>
<h4><xsl:value-of select="$key" /></h4>
    <h4>
      <xsl:for-each select="($abc)/value">
<xsl:variable name="some" select="text()" />
<xsl:value-of select="concat($some,':')" />
        <xsl:for-each select="($value)/value">
<xsl:variable name="other" select="text()" />
        <xsl:if test="contains($other,$some)">
<xsl:value-of select="concat(text(),';')" />
        </xsl:if>
        </xsl:for-each>
      </xsl:for-each>
    </h4>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
        <th>variable</th>
      </tr>
      <xsl:for-each select="catalog/cd/title">
      <tr>
        <td><xsl:value-of select="concat(substring-before(current(),'_'),':',current())" /></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

可以看出,我仍在努力实现我想要的输出。我非常厌倦 XSL 的 constant 变量。任何帮助表示赞赏。 提前致谢。

Link在线XML变压器: https://www.freeformatter.com/xsl-transformer.html

要实现您在 XSLT-1.0 中提到的结果(因为 distinct-values() 功能在 XSLT-1.0 中不可用),添加以下键

<xsl:key name="titles" match="catalog/cd/title" use="substring-before(.,'_')" />

然后像这样在你的变量中使用它(这就是上面提到的调用 Muenchian Grouping):

<xsl:variable name="abc">
    <xsl:for-each select="/catalog/cd/title[generate-id(.) = generate-id(key('titles',substring-before(.,'_'))[1])]">
        <xsl:value-of select="substring-before(.,'_')" /><xsl:text>: </xsl:text>
        <xsl:for-each select="key('titles',substring-before(.,'_'))">
            <xsl:value-of select="." />
            <xsl:if test="position() != last()"><xsl:text>;</xsl:text></xsl:if>
        </xsl:for-each>
        <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
</xsl:variable>

如果你再用

输出变量
<xsl:copy-of select="$abc" />

您将得到以下结果:

Empire: Empire_Burlesque_something;Empire_Burlesque_other
Home: Home_Empire_Burlesque

有了这些知识,您就可以完成创建 HTML 文件的任务。
您也应该通过添加

将输出方法更改为“HTML”
<xsl:output method="html" />

到 XSLT 的根元素。