【问题标题】:Change format of comma delimited tags in xml using xslt?使用xslt更改xml中逗号分隔标签的格式?
【发布时间】:2014-03-20 11:34:51
【问题描述】:

我有一个 xml 文档,其中包含这样的逗号分隔标签...

<?xml version="1.0" encoding="utf-8" ?>
<pages>
    <page>
        <tags>AAMC 2013, Learning Health System, Cost</tags>
    </page>
    <page>
        <tags>AAMC 2013, Cost, Innovation</tags>
    </page>
    <page>
        <tags>AAMC 2013, Cost, Innovation</tags>
    </page>
</pages>

是否可以使用 xslt 更改 xml 以显示更像下面的代码,它分隔标签名称并计算标签被引用的次数?

<?xml version="1.0" encoding="utf-8" ?>
<pages>
    <page>
        <tag>
            <name>AAMC 2013</name>
            <amount>3</amount>
        </tag>
        <tag>
            <name>Learning Health System</name>
            <amount>1</amount>
        </tag>
        <tag>
            <name>Cost</name>
            <amount>3</amount>
        </tag>
     </page>
    <page>
        <tag>
            <name>AAMC 2013</name>
            <amount>3</amount>
        </tag>
        <tag>
            <name>Cost</name>
            <amount>3</amount>
        </tag>
        <tag>
            <name>Innovation</name>
            <amount>2</amount>
        </tag>
    </page>
    <page>
        <tag>
            <name>AAMC 2013</name>
            <amount>3</amount>
        </tag>
        <tag>
            <name>Cost</name>
            <amount>3</amount>
        </tag>
        <tag>
            <name>Innovation</name>
            <amount>2</amount>
        </tag>
    </page>
</pages> 

感谢您的帮助。

【问题讨论】:

  • 什么版本的 xslt?

标签: html xml xslt xslt-1.0


【解决方案1】:

IIUC,这里有两个任务:

  1. 标记标签;

  2. 统计每个标签的出现次数。

第二个任务需要第一个任务的输出作为其输入 - 所以我们需要分两次完成:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="sametag" match="token" use="." />

<xsl:template match="/">
<!-- first pass -->
<xsl:variable name="tagnames">
    <xsl:for-each select="pages/page">
        <page>
            <xsl:call-template name="tokenize">
                <xsl:with-param name="string" select="tags" />
            </xsl:call-template>
        </page>
    </xsl:for-each>
</xsl:variable>
<xsl:variable name="tagnames-set" select="exsl:node-set($tagnames)" />
<!-- second (final) pass -->
<pages>
    <xsl:for-each select="$tagnames-set/page">
        <page>
        <xsl:for-each select="token">
            <tag>
                <name><xsl:value-of select="." /></name>
                <amount><xsl:value-of select="count(key('sametag', .))" /></amount>
            </tag>
        </xsl:for-each>
        </page>
    </xsl:for-each>
</pages>
</xsl:template>

<xsl:template name="tokenize">
    <xsl:param name="string"/>
    <xsl:param name="delimiter" select="', '"/>
    <xsl:choose>
        <xsl:when test="contains($string, $delimiter)">
            <token><xsl:value-of select="substring-before($string, $delimiter)" /></token>
            <!-- recursive call -->
            <xsl:call-template name="tokenize">
                <xsl:with-param name="string" select="substring-after($string, $delimiter)" />
                <xsl:with-param name="delimiter" select="$delimiter" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <token><xsl:value-of select="$string"/></token>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

请注意,这需要 XSLT 1.0 处理器广泛支持的 EXSLT node-set() 函数。如果您的处理器支持 EXSLT tokenize() 函数,那么您可以使用它来代替标记化模板。其输出已经是一个节点集,因此将大大简化样式表。

【讨论】:

  • 感谢您的回复。我正在尝试一些不同的东西,我改变了我的问题以使其更有意义......我想。抱歉,我是新手。
  • @Jonathan 请再次编辑您的问题并确保输入和输出 XML 文档均有效;现在他们都缺少一个根元素。我会自己添加一个,但您已经在页面中包含页面,恐怕我的示例不适合您的真实数据。
猜你喜欢
  • 1970-01-01
  • 2014-03-11
  • 2013-11-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
相关资源
最近更新 更多