最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Use a variable inside a CDATA block, in Javascript? - Stack Overflow

programmeradmin1浏览0评论

CDATA-blocks work great for coding large blocks of HTML, or CSS, into strings. But, I can't figure out how to use a variable-value within one.

For example, consider this JavaScript code:

var FullName    = "Friedrich Hayek";
var ProfileCode = (<><![CDATA[
                    <div id="BigHonkingChunkO_HTML">
                        ...Lot's o' code...

                        Name: $FullName$
                        Birth: $Birthdate$

                        ...Lot's o' code...

                        ... $FullName$ ...

                        ...Lot's o' code...
                    </div>
                ]]></>).toString ();


How do I get $FullName$ to render as "Friedrich Hayek" instead of "$FullName$"?

Note that there is more than one variable and each variable can be used a few times in the CDATA block.


Alternate code sample:

var UserColorPref   = "red";
var UI_CSS          = (<><![CDATA[
                        body {
                            color:              $UserColorPref$;
                        }
                    ]]></>).toString ();

Looking to set the color attribute to red.

CDATA-blocks work great for coding large blocks of HTML, or CSS, into strings. But, I can't figure out how to use a variable-value within one.

For example, consider this JavaScript code:

var FullName    = "Friedrich Hayek";
var ProfileCode = (<><![CDATA[
                    <div id="BigHonkingChunkO_HTML">
                        ...Lot's o' code...

                        Name: $FullName$
                        Birth: $Birthdate$

                        ...Lot's o' code...

                        ... $FullName$ ...

                        ...Lot's o' code...
                    </div>
                ]]></>).toString ();


How do I get $FullName$ to render as "Friedrich Hayek" instead of "$FullName$"?

Note that there is more than one variable and each variable can be used a few times in the CDATA block.


Alternate code sample:

var UserColorPref   = "red";
var UI_CSS          = (<><![CDATA[
                        body {
                            color:              $UserColorPref$;
                        }
                    ]]></>).toString ();

Looking to set the color attribute to red.

Share Improve this question edited Jul 17, 2011 at 6:37 Brock Adams asked Jan 9, 2011 at 2:34 Brock AdamsBrock Adams 93.7k23 gold badges241 silver badges305 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

Is it elegant enough ?

function replaceVars(content, vars)
{
    return content.replace(/\$(\w+)\$/g, function($0, $1)
    {
        return ($1 in vars ? vars[$1] : $0);
    });
}

ProfileCode = replaceVars(ProfileCode, {"FullName" : "Friedrich Hayek"});

In case associative keys don't really matter, you can always opt to use:
sprintf or vsprintf

EDIT

What about making the 2nd parameter optional ?

function replaceVars(content, scope) {
    if (!scope || typeof scope != "object") {
        scope = this;
    }

    return content.replace(/\$(\w+)\$/g, function($0, $1) {
        return ($1 in scope ? scope[$1] : $0);
    });
}

// example1
var FullName = "Friedrich Hayek";
ProfileCode = replaceVars(ProfileCode);

// example2
var vars = {"FullName" : "Friedrich Hayek"};
ProfileCode = replaceVars(ProfileCode, vars);
ProfileCode=ProfileCode.replace('$FullName$',FullName);

After scouring the CDATA spec, and this "CDATA Confusion" article, it seems that CDATA sections treat everything as pure text, except for character-data entities and the section end marker (]]>). For example,

var x = $('<!DOCTYPE X[<!ENTITY foo "BAR">]><z> cc &#65; &foo;</z>');
console.log ($(x, 'z').text() );

Yields: ]> cc A &foo;

So, there's no way to have variable substitution within a CDATA section. The best we can do is start and stop the sections, like so:

var FullName    = "Friedrich Hayek";
var ProfileCode = (<><![CDATA[
                    <div id="BigHonkingChunkO_HTML">
                        ...Lot's o' code...

                        Name: ]]></>).toString () + FullName+ (<><![CDATA[

                        ...Lot's o' code...
                    </div>
                ]]></>).toString ();
console.log (ProfileCode);

-- which is obviously not acceptable.


Practical workaround:

It won't help anyone looking for a CDATA solution (which we now know is impossible, per the spec). But as we were just using CDATA as a method to generate a plex string, then we can clean the string up afterwards, per Ratna Dinakar's answer.

The function we ended up using is:

function sSetVarValues (sSrcStr, sReplaceList /* , Variable */)
/*--- function sSetVarValues takes a string and substitutes marked
    locations with the values of the variables represented.
    Conceptually, sSetVarValues() operates a little like sprintf().

    Parameters:
        sSrcStr         --  The source string to be replaced.   
        sReplaceList    --  A string containing a ma-separated list of variable
                            names expected in the raw string.  For example, if 
                            sReplaceList was "Var_A", we would expect (but not require)
                            that sSrcStr contained one or more "$Var_A$" substrings.
        *Variable*      --  A variable-length set of parameters, containing the values
                            of the variables specified in sReplaceList.  For example,
                            if sReplaceList was "Var_A, Var_B, Var_C", then there better 
                            be 3 parameters after sReplaceList in the function call. 
    Returns:                The replaced string.
*/
{
    if (!sSrcStr)       return null;
    if (!sReplaceList)  return null;

    var aReplaceList    = sReplaceList.split (/,\s?/);

    for (var J = aReplaceList.length-1;  J >= 0;  --J)
    {
        var zRepVar     = new RegExp ('\\$' + aReplaceList[J] + '\\$', "g");
        sSrcStr         = sSrcStr.replace (zRepVar, arguments[J+2]);
    }
    return sSrcStr;
}


Sample use:

var AAA     = 'first';
var BBB     = 'second'; 
var CCC     = 'third';
var Before  = "1 is $AAA$, 2 is $BBB$, 3 is $CCC$";

var After   = sSetVarValues (Before, "AAA, BBB, CCC", AAA, BBB, CCC);

console.log (Before);
console.log (After);

Yields:

    1 is $AAA$, 2 is $BBB$, 3 is $CCC$
    1 is first, 2 is second, 3 is third

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论