【问题标题】:XSLT Check the presence of a substring and then print if existXSLT 检查子字符串是否存在,如果存在则打印
【发布时间】:2020-08-28 23:39:30
【问题描述】:

考虑以下 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 变量。任何帮助表示赞赏。 提前致谢。

在线 XML 转换器的链接: https://www.freeformatter.com/xsl-transformer.html

【问题讨论】:

  • 另外,如果有人说我可以使用模板轻松完成它,可能但我仍然掌握 XSL 本身,还没有达到我对语言足够好的程度粗暴地进入 XSL 模板,仍然无法理解。而且,我们也可以忽略 XSL 文件中的“表格”。
  • 1. 您的问题被标记为 XSLT 1.0(您的样式表也是如此) - 但 distinct-values() 需要 XSLT 2.0。 --- 2. 这是一个分组问题。 XSLT 1.0 中的分组最好使用 Muenchian 方法 - 请参阅:jenitennison.com/xslt/grouping/muenchian.html
  • 这是非常有用的信息 Michael @michael.hor257k

标签: xml xslt xslt-1.0


【解决方案1】:

要达到你在 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_Burlesque_something;Empire_Burlesque_other
主页:Home_Empire_Burlesque

有了这些知识,您就可以完成创建 HTML 文件的任务。
您可能也应该通过添加将输出方法更改为“HTML”

<xsl:output method="html" />

到 XSLT 的根元素。

【讨论】:

  • 明确表示要避免对 +1 或大拇指或类似的评论,这就是我没有这样做的原因。但我想谢谢你,所以就这样。由于我是新人,如果有什么方法可以按照定义的方式感谢,请让我知道,我会答应的。
  • 对于提问者,如果您问的是,点击接受箭头算作“谢谢,这对您的帮助最大”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
  • 2019-11-04
  • 2021-10-25
相关资源
最近更新 更多