使用sprintf输出XML标记

使用sprintf输出XML标记

问题描述:

I have a few XML templates that I am trying to fill using PHP's sprintf (v.5.3.8-Win54); however, I noticed that sprintf seems to be having problems with the < character. It seems that the < character needs to be followed by a space in order for sprintf to output it correctly. I looked at the PHP sprintf documentation but I couldn't find any references to any special character besides %. I echoed the following examples using echo sprintf($format1, $name, $age); to show the problem:

$name = 'Lame';
$age = 1000;
$format1 = 'My name is %s. I am %d years old.';
$format2 = '<name> %s </name><age> %d </age>';
$format3 = 'name> %s /name>age> %d /age>';
$format4 = '<name %s </name<age %d </age';
$format5 = '<name> %s </name><age> %d </age>';

The formats are echoed as:

FORMAT 1: My name is Lame. I am 1000 years old.  
FORMAT 2: Lame 1000  
FORMAT 3: name> Lame /name>age> 1000 /age>  
FORMAT 4:   
FORMAT 5: <name> Lame </name><age> 1000 </age>  

*FORMAT 4 does indeed come out as blank.

Any ideas why the < character isn't being output unless there is a space following it? I suppose I could just add a space to all the < characters in the XML templates using find/replace, but I rather find out why this is happening to begin with. I have a feeling this is going to be basic knowledge that I just haven't come across yet; if so, can you please provide references to any documentation?

INTERESTING: I had to add a space after the < character while typing out this question in the Stackoverflow interface so that it would appear correctly in the FORMAT 5 line! Huuuuuuh??!

* COMPLETE CODE *

<?php   
$name = 'Lame';
$age = 1000;
$format1 = 'My name is %s. I am %d years old.';
$format2 = '<name> %s </name><age> %d </age>';
$format3 = 'name> %s /name>age> %d /age>';
$format4 = '<name %s </name<age %d </age';
$format5 = '< name> %s < /name>< age> %d < /age>';


echo 'FORMAT 1: ';
echo sprintf($format1, $name, $age);

echo '<br>';

echo 'FORMAT 2: ';
echo sprintf($format2, $name, $age);

echo '<br>';

echo 'FORMAT 3: ';
echo sprintf($format3, $name, $age);

echo '<br>';

echo 'FORMAT 4: ';
echo sprintf($format4, $name, $age);

echo '<br>';
echo '<br>';

echo 'FORMAT 5: ';
echo sprintf($format5, $name, $age);

?>

I think I understand the issue; to fully clarify what I'm thinking: you're directly looking at the results of the sprintf() outputs in a browser - not through View Source mode or via Command Line but literally "as it displays".

This explains your results. Let's take Format #2 for example:

<name> %s </name><age> %d </age>

If you take this exact line of text and save it in a file named test.html and open it in a web-browser, you will see:

%s %d

This is because the browser interprets <name> and <age> as HTML tags and will not display them textually.

The same can be applied to Format #4 and why it "doesn't display at all". The first <name tag doesn't end so the browser assumes all of the text in that line are attributes belonging to said tag.

For all of the above, if you "View Source" on the page you're looking at - you'll see the correct output that you'd expect/want to see.

If your intent is to actually see a textual representation of the output, such as <name>Lame</name>, you can use PHP's htmlentities or htmlspecialchars on each of the outputs:

echo 'FORMAT 2: ';
echo htmlentities(sprintf($format2, $name, $age));
echo '<br />';

These functions will "convert applicable characters to HTML". In this specific case, < and > are the important ones =]

You probably want to wrap you strings in htmlspecialchars()

http://www.php.net/manual/en/function.htmlspecialchars.php

That function will automatically convert your html symbols into encoded equivalents to be displayed on a web page.