سؤال

I almost have my transform working but the final piece is eluding me.

My input 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>

The goal is to get this out:

<?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';

Where the PH tags with a CONREF output the referred-to PH's value.

My current XSLT is:

<?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>

The last part with match="sectiondiv/ph[@conref]" is the issue. I have tried using a variable 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>

which seemed promising until I found out that an XSL "variable" is actually a runtime constant, and I was getting:

<?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';

I also tried using <xsl:value-of select="//ph[string(@conref)]" disable-output-escaping="yes" />

I'm sure there's an easy solution, but I am not familiar with XSL (so naturally I'm the one who gets to work on it.)

P.S. Sorry for the long-lines, but I am additionally having many issues with line breaks being inserted where I cannot tolerate them, so this was the best fix I found so far.

P.P.S Sorry for the lack of syntax highlighting but I could not seem to get it working.

هل كانت مفيدة؟

المحلول

You have to extract the id from the @conref attribute, and then compare it to the @id of the ph you want to replace. You can use a variable to save the extracted ID:

<xsl:template match="sectiondiv/ph[@conref]">
    <xsl:variable name="id" select="substring-after(@conref, '#doc/')"/>
    ...

And then use it to select which ph element will be replaced:

<xsl:value-of select="//ph[$id = @id]" />

You should also place your text within <xsl:text> to control the spaces in your output. Replace these templates in your XSL and you should obtain the result you expect:

<!-- Replace ph with $lang variables -->
<xsl:template match="sectiondiv/ph[not(@conref)]">
    <xsl:text>$lang['</xsl:text><xsl:value-of select="@id" /><xsl:text>'] = '</xsl:text>
    <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]">
    <xsl:variable name="id" select="substring-after(@conref, '/')"/>
    <xsl:text>$lang['</xsl:text><xsl:value-of select="@id" /><xsl:text>'] = '</xsl:text>
    <xsl:value-of select="//ph[$id = @id]" disable-output-escaping="yes" />
    <xsl:text>';&#xa;</xsl:text>
</xsl:template>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top