使用动态查找的 XSLT 转换

XSLT transform with dynamic lookups

我需要转换看起来像这样的数据。对于每个用户,我需要读取 idcode 属性,从 idcode 标签中获取适当的值,并将它们一起输出。用户可以有多个逗号分隔的 idcode。用户列表、每次使用的 ID 和 ID 查找列表都可以任意大。

输入:

<users>
  <user idcode="1">Doug Edmonds</user>
  <user idcode="2">Jay P. Dunn</user>
  <user idcode="4,5">Gerard A. Kriss</user>
  <user idcode="6">Kirk Korista</user>
  <idcode id="1">100</idcode>
  <idcode id="2">254</idcode>
  <idcode id="3">854</idcode>
  <idcode id="4">741</idcode>
  <idcode id="5">965</idcode>
  <idcode id="6">571</idcode>
</users>

期望的输出:

<systemUser>Doug Edmonds</systemUser>
<systemId value="100"/>
<systemUser>Jay P. Dunn</systemUser>
<systemId value="254"/>
<systemUser>Gerard A. Kriss</systemUser>
<systemId value="741"/>
<systemId value="965"/>
<systemUser>Kirk Korista</systemUser>
<systemId value="571"/>

我一直在修改的 xslt 是:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
                xmlns:xhtml="http://www.w3.org/1999/xhtml"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xhtml xsl xs">

    <xsl:output method="xhtml"/>

    <xsl:template match="header">
        <xsl:apply-templates select="users/user" />
    </xsl:template>

    <xsl:template match="user">
        <xsl:variable name="userName" select="."/>
        <xsl:variable name="userId" select="./@idcode"/>
        <user>{$userName}</user>
        <xsl:variable name="tokenizedId" select="tokenize($userId,',')"/>
        <xsl:for-each select="$tokenizedId">
            <xsl:variable name="singleId" select="."/>
            <xsl:variable name="systemId" select="./users/idcode[@id = '{$singleId}']"/>
            <systemId" value="{$systemId}"/>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

你用的是 ./@idcode,但实际上是 ../@idcode

另请注意,XPath = 运算符适用于序列,因此您不需要 $singleId

怎么样:

<xsl:stylesheet version="2.0"
                xmlns:xhtml="http://www.w3.org/1999/xhtml"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xhtml xsl xs">

    <xsl:output method="xhtml"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="user">
        <user><xsl:value-of select="." /></user>
        <xsl:apply-templates select="../idcode[@id = tokenize(current()/@idcode, ',')]" mode="systemId" />
    </xsl:template>

    <xsl:template match="idcode" mode="systemId">
        <systemId value="{.}" />
    </xsl:template>

    <xsl:template match="idcode" />
</xsl:stylesheet>

当然,如果您愿意,同样的事情也可以用 for-each 来表达。

<xsl:stylesheet version="2.0"
                xmlns:xhtml="http://www.w3.org/1999/xhtml"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xhtml xsl xs">

    <xsl:output method="xhtml"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="user">
        <user><xsl:value-of select="." /></user>
        <xsl:for-each select="../idcode[@id = tokenize(current()/@idcode, ',')]">
            <systemId value="{.}" />
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="idcode" />
</xsl:stylesheet>

您可以声明一个键来交叉引用 idcode 并按如下方式使用它:

<xsl:stylesheet version="2.0" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xhtml xsl xs">
    <xsl:output method="xhtml" indent="yes"/>

    <xsl:key name="idcode" match="/users/idcode" use="@id"/>

    <xsl:template match="/">
        <output>
            <xsl:apply-templates select="users/user" />
        </output>
    </xsl:template>

    <xsl:template match="users/user">
        <systemUser>
            <xsl:value-of select="."/>
        </systemUser>
        <xsl:apply-templates select="key('idcode', tokenize(@idcode, ','))"/>
    </xsl:template>

    <xsl:template match="idcode">
        <systemId value="{.}"/>
    </xsl:template>

</xsl:stylesheet>