XSLT 1.0转换为其id获取另一个标记值

时间:2014-04-02 19:31:09

标签: xpath xslt-1.0

我几乎让我的变换工作,但最后一件事是在逃避我。

我的输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE reference PUBLIC "-//OASIS//DTD DITA Reference//EN"
"/SysSchema/dita/dtd/technicalContent/dtd/reference.dtd">
<reference xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/"
ditaarch:DITAArchVersion="1.2" xml:lang="en-US" id="doc">
    <title>Title</title>
    <refbody>
        <section>
            <draft-comment outputclass="PHP" translate="no">//
Comment</draft-comment>
            <sectiondiv><ph id="r1">A</ph></sectiondiv>
            <sectiondiv><ph id="r2">B</ph></sectiondiv>
        </section>
        <section>
            <sectiondiv><ph id="r3" conref="#doc/r1" /></sectiondiv>
            <sectiondiv><ph id="r4" conref="#doc/r2" /></sectiondiv>
            <sectiondiv><ph id="r5">C</ph></sectiondiv>
        </section>
    </refbody>
</reference>

目标是解决这个问题:

<?php if (! defined('BASEPATH')) exit('No direct script access allowed');

// Comment
$lang['r1'] = 'A';
$lang['r2'] = 'B';
$lang['r3'] = 'A';
$lang['r4'] = 'B';
$lang['r5'] = 'C';

带有CONREF的PH标签输出所引用的PH值。

我目前的XSLT是:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="no" omit-xml-declaration="yes" />

    <!-- strip all white space -->
    <xsl:strip-space elements="*" />

    <!-- remove unnecessary tags -->
    <xsl:template match="section">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="sectiondiv">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="refbody">
        <xsl:apply-templates />
    </xsl:template>

    <!-- Copy XML -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <!-- Add PHP script access code-->
    <xsl:template match="/">
        <xsl:text disable-output-escaping="yes">&lt;?php if (! defined('BASEPATH')) exit('No direct script access allowed');</xsl:text>
        <xsl:text>&#xa;&#xa;</xsl:text>
        <xsl:apply-templates select="/reference/refbody" />
    </xsl:template>

    <!-- Convert draft-comment to php comment -->
    <xsl:template match="//draft-comment[@outputclass='PHP']">
        <xsl:value-of select="." />
        <xsl:text>&#xa;</xsl:text>
    </xsl:template>

    <!-- Replace ph with $lang variables -->
    <xsl:template match="sectiondiv/ph[not(@conref)]">$lang['<xsl:value-of select="@id" />'] = '<xsl:value-of select="." disable-output-escaping="yes" />';<xsl:text>&#xa;</xsl:text></xsl:template>

    <!-- Replace ph with $lang variables -->
    <xsl:template match="sectiondiv/ph[@conref]">$lang['<xsl:value-of select="@id" />'] = '<xsl:value-of select="//ph[@conref]" disable-output-escaping="yes" />';<xsl:text>&#xa;</xsl:text></xsl:template>

</xsl:stylesheet>

match="sectiondiv/ph[@conref]"的最后一部分是问题所在。我尝试过使用变量ala:

<xsl:template match="sectiondiv/ph[@conref]"><xsl:variable name="refid" select="@conref" />$lang['<xsl:value-of select="@id" />'] = '<xsl:value-of select="//ph[$refid]" disable-output-escaping="yes" />';<xsl:text>&#xa;</xsl:text></xsl:template>

看起来很有希望,直到我发现XSL&#34;变量&#34;实际上是一个运行时常量,我得到了:

<?php if (! defined('BASEPATH')) exit('No direct script access allowed');

// Comment
$lang['r1'] = 'A';
$lang['r2'] = 'B';
$lang['r3'] = 'A';
$lang['r4'] = 'A';
$lang['r5'] = 'C';

我也尝试过使用<xsl:value-of select="//ph[string(@conref)]" disable-output-escaping="yes" />

我确信这是一个简单的解决方案,但我对XSL并不熟悉(所以我自然而然就是那个开始研究它的人。)

P.S。很抱歉有很长的路线,但我还有很多插入换行符的问题,我无法容忍它们,所以这是我到目前为止找到的最佳解决方案。

P.P.S很抱歉没有语法高亮,但我似乎无法让它发挥作用。

1 个答案:

答案 0 :(得分:1)

您必须从@conref属性中提取 id ,然后将其与要替换的@id的{​​{1}}进行比较。您可以使用变量来保存提取的ID:

ph

然后使用它来选择要替换的<xsl:template match="sectiondiv/ph[@conref]"> <xsl:variable name="id" select="substring-after(@conref, '#doc/')"/> ... 元素:

ph

您还应将文字放在<xsl:value-of select="//ph[$id = @id]" /> 中以控制输出中的空格。在XSL中替换这些模板,您应该获得预期的结果:

<xsl:text>