如何迭代多个交叉引用?

时间:2013-07-10 19:59:56

标签: xml xslt

我的XML源指定linkGrp中的交叉引用。基于那些 @target属性指定的交叉引用,我需要分组 s元素的值。如果target属性包含一对一 参考,我的代码运作良好如下:

<DIV>
    <div id="e">
        <s id="e1">AAAAA</s>
        <s id="e2">BBBBB</s>
        <s id="e3">CCCCC</s>
    </div>
    <div id="fr">
        <s id="fr1">DDDDD</s>
        <s id="fr2">EEEEE</s>
        <s id="fr3">FFFFF</s>
    </div>
    <linkGrp type="alignment" domains="e fr">
        <link target="#e1 #fr1"/>
        <link target="#e2 #fr3"/>
        <link target="#e3 #fr2"/>
    </linkGrp>
</DIV>

我得到的HTML输出是:

*AAAAA
DDDDD

*BBBBB
FFFFF

*CCCCC
EEEEE

要获得此结果,我使用以下XSLT代码:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="linkId" match="s" use="@id"/>
    <xsl:template match="/DIV">
        <html>
            <head>
                <title>Test</title>
            </head>
            <body>
                <xsl:apply-templates/>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="link">
        <ul>
            <li>
                <xsl:value-of select="key('linkId',substring-before(substring-after(@target, '#'), ' '))"/>
                <br/>
                <xsl:value-of select="key('linkId',substring-after(@target, ' #'))"/>
            </li>
        </ul>
    </xsl:template>
    <xsl:template match="div"/>
    <xsl:template match="s"/>
    <xsl:template match="*">
        <xsl:message terminate="no">
            WARNING: Unmatched element: <xsl:value-of select="name()"/>
        </xsl:message>
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>

但是,当我在link元素中为一个@target添加更多交叉引用时,我的XSLT代码效果不佳:

<DIV>
    <div id="e">
        <s id="e1">AAAAA</s>
        <s id="e2">BBBBB</s>
        <s id="e3">CCCCC</s>
    </div>
    <div id="fr">
        <s id="fr1">DDDDD</s>
        <s id="fr2">EEEEE</s>
        <s id="fr3">FFFFF</s>
    </div>
    <linkGrp type="alignment" domains="e fr">
        <link target="#e1 #fr1"/>
        <link target="#e2 #fr3 #fr1 #fr2"/>
        <link target="#e3 #fr2 #fr3"/>
    </linkGrp>
</DIV>

在XML源代码中有多个交叉引用,我的XSLT代码无法获取 任何比赛。我需要我的代码来检索@target中指定的所有匹配项 属性。任何人都可以在我的XSLT代码中指出错误或提供替代方案 溶液

1 个答案:

答案 0 :(得分:0)

使用xslt-1.0,您可以使用递归模板调用来拆分ID。 尝试这样的事情:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="linkId" match="s" use="@id"/>
    <xsl:template match="/DIV">
        <html>
            <head>
                <title>Test</title>
            </head>
            <body>
                <xsl:apply-templates/>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="link">
        <ul>
            <li>
                <xsl:call-template name="findtarget">
                    <xsl:with-param name="targets" select="@target" />
                </xsl:call-template>
            </li>
        </ul>
    </xsl:template>


    <xsl:template name="findtarget">
        <xsl:param name="targets" />
        <xsl:choose>
            <xsl:when test="contains($targets, ' ')">
                <xsl:call-template name="findtarget">
                    <xsl:with-param name="targets" select="substring-before($targets,' ')" />
                </xsl:call-template>
                <br/>
                <xsl:call-template name="findtarget">
                    <xsl:with-param name="targets" select="substring-after($targets,' ')" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="key('linkId',substring-after($targets, '#'))"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="div"/>
    <xsl:template match="s"/>
    <xsl:template match="*">
        <xsl:message terminate="no">
            WARNING: Unmatched element: <xsl:value-of select="name()"/>
        </xsl:message>
        <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>

将生成以下输出:

                     WARNING: Unmatched element: linkGrp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test</title>
</head>
<body>



                <ul><li>AAAAA<br>DDDDD</li></ul>
                <ul><li>BBBBB<br>FFFFF<br>DDDDD<br>EEEEE</li></ul>
                <ul><li>CCCCC<br>EEEEE<br>FFFFF</li></ul>

</body>
</html>

另一种解决方案可能是使用xpath函数id()。但要使其工作,您的XML需要具有DTD DOCTYPE。 像这样:

<!DOCTYPE DIV  [
<!ATTLIST s
  id     ID    #REQUIRED
>
]>
<DIV>
    <div id="e">
        <s id="e1">AAAAA</s>
        <s id="e2">BBBBB</s>
        <s id="e3">CCCCC</s>
    </div>
    <div id="fr">
        <s id="fr1">DDDDD</s>
        <s id="fr2">EEEEE</s>
        <s id="fr3">FFFFF</s>
    </div>
    <linkGrp type="alignment" domains="e fr">
        <link target="#e1 #fr1"/>
        <link target="#e2 #fr3 #fr1 #fr2"/>
        <link target="#e3 #fr2 #fr3"/>
    </linkGrp>
</DIV>

使用此XML,您的链接模板可能会更改如下:

<xsl:template match="link">
    <ul>
        <li>
            <xsl:for-each select="id(translate(@target,'#', ''))">
                <xsl:if test="position() > 1">
                    <br/>
                </xsl:if>
                <xsl:value-of select="."/>
            </xsl:for-each>
        </li>
    </ul>
</xsl:template>