首页 文章

用PHP生成XML文档(转义字符)

提问于
浏览
45

我正在从PHP脚本生成XML文档,我需要转义XML特殊字符 . 我知道应该转义的字符列表;但是这样做的正确方法是什么?

是否应该使用反斜杠(')或正确的方式转义字符?是否有任何内置的PHP函数可以为我处理这个?

10 回答

  • 2

    使用DOM类生成整个XML文档 . 它将处理我们甚至不想关心的编码和解码 .


    编辑:这被@Tchalvak批评:

    DOM对象创建一个完整的XML文档,它不仅仅是为了自己编写一个字符串 .

    哪个错了,DOMDocument可以正确输出一个片段而不是整个文档:

    $doc->saveXML($fragment);
    

    这使:

    Test &amp; <b> and encode </b> :)
    Test &amp;amp; &lt;b&gt; and encode &lt;/b&gt; :)
    

    如:

    $doc = new DOMDocument();
    $fragment = $doc->createDocumentFragment();
    
    // adding XML verbatim:
    $xml = "Test &amp; <b> and encode </b> :)\n";
    $fragment->appendXML($xml);
    
    // adding text:
    $text = $xml;
    $fragment->appendChild($doc->createTextNode($text));
    
    // output the result
    echo $doc->saveXML($fragment);
    

    Demo

  • -2

    我创建了一个简单的函数,它与XML中的five "predefined entities"一起转义:

    function xml_entities($string) {
        return strtr(
            $string, 
            array(
                "<" => "&lt;",
                ">" => "&gt;",
                '"' => "&quot;",
                "'" => "&apos;",
                "&" => "&amp;",
            )
        );
    }
    

    用法示例Demo

    $text = "Test &amp; <b> and encode </b> :)";
    echo xml_entities($text);
    

    输出:

    Test &amp;amp; &lt;b&gt; and encode &lt;/b&gt; :)
    

    使用 str_replace 可以实现类似的效果,但由于双重替换(未经测试,不推荐),它很脆弱:

    function xml_entities($string) {
        return str_replace(
            array("&",     "<",    ">",    '"',      "'"),
            array("&amp;", "&lt;", "&gt;", "&quot;", "&apos;"), 
            $string
        );
    }
    
  • 0

    htmlspecialchars()功能怎么样?

    htmlspecialchars($input, ENT_QUOTES | ENT_XML1, $encoding);
    

    Note: ENT_XML1 标志仅在PHP 5.4.0或更高版本可用时才可用 .

    带有这些参数的 htmlspecialchars() 将替换以下字符:

    • & (&符号)变为 &amp;

    • " (双引号)变为 &quot;

    • ' (单引号)变为 &apos;

    • < (小于)变为 &lt;

    • > (大于)变为 &gt;

    您可以使用get_html_translation_table()函数获取转换表 .

  • 1

    试图处理XML实体问题,以这种方式解决:

    htmlspecialchars($value, ENT_QUOTES, 'UTF-8')
    
  • 35

    为了获得有效的最终XML文本,您需要转义所有XML实体,并使用与XML文档处理指令相同的编码来编写文本( <?xml 行中的"encoding") . 只要将重音字符编码为文档,就不需要对其进行转义 .

    但是,在许多情况下,简单地使用 htmlspecialchars 转义输入可能会导致双重编码实体(例如 &eacute; 将变为 &amp;eacute; ),因此我建议首先解码html实体:

    function xml_escape($s)
    {
        $s = html_entity_decode($s, ENT_QUOTES, 'UTF-8');
        $s = htmlspecialchars($s, ENT_QUOTES, 'UTF-8', false);
        return $s;
    }
    

    现在,您需要确保所有重音字符在XML文档编码中都有效 . 我强烈建议始终以UTF-8编码XML输出,因为并非所有XML解析器都遵循XML文档处理指令编码 . 如果您的输入可能来自不同的字符集,请尝试使用 utf8_encode() .

    有一个特殊情况,你的输入可能来自以下编码之一:ISO-8859-1,ISO-8859-15,UTF-8,cp866,cp1251,cp1252和KOI8-R - PHP将它们全部视为同样,但它们之间存在一些细微的差别 - 其中一些甚至 iconv() 无法处理 . 我只能通过补充 utf8_encode() 行为来解决这个编码问题:

    function encode_utf8($s)
    {
        $cp1252_map = array(
        "\xc2\x80" => "\xe2\x82\xac",
        "\xc2\x82" => "\xe2\x80\x9a",
        "\xc2\x83" => "\xc6\x92",
        "\xc2\x84" => "\xe2\x80\x9e",
        "\xc2\x85" => "\xe2\x80\xa6",
        "\xc2\x86" => "\xe2\x80\xa0",
        "\xc2\x87" => "\xe2\x80\xa1",
        "\xc2\x88" => "\xcb\x86",
        "\xc2\x89" => "\xe2\x80\xb0",
        "\xc2\x8a" => "\xc5\xa0",
        "\xc2\x8b" => "\xe2\x80\xb9",
        "\xc2\x8c" => "\xc5\x92",
        "\xc2\x8e" => "\xc5\xbd",
        "\xc2\x91" => "\xe2\x80\x98",
        "\xc2\x92" => "\xe2\x80\x99",
        "\xc2\x93" => "\xe2\x80\x9c",
        "\xc2\x94" => "\xe2\x80\x9d",
        "\xc2\x95" => "\xe2\x80\xa2",
        "\xc2\x96" => "\xe2\x80\x93",
        "\xc2\x97" => "\xe2\x80\x94",
        "\xc2\x98" => "\xcb\x9c",
        "\xc2\x99" => "\xe2\x84\xa2",
        "\xc2\x9a" => "\xc5\xa1",
        "\xc2\x9b" => "\xe2\x80\xba",
        "\xc2\x9c" => "\xc5\x93",
        "\xc2\x9e" => "\xc5\xbe",
        "\xc2\x9f" => "\xc5\xb8"
        );
        $s=strtr(utf8_encode($s), $cp1252_map);
        return $s;
    }
    
  • 16

    如果你需要正确的xml输出,simplexml是要走的路:

    http://www.php.net/manual/en/simplexmlelement.asxml.php

  • 13

    正确转义是获取正确XML输出的方法,但您需要处理Java codeelements 的转义 differently . (这是托马斯的回答是不正确的) .

    我写了/偷了一些Java code,后来区分属性和元素转义 . 原因是XML解析器特别在属性中考虑所有空白区域 .

    将它移植到PHP应该是微不足道的(如果你使用 UTF-8 ,你可以使用Tomas Jancik 's approach with the above appropriate escaping). You don' t担心转义扩展实体 .

    如果您不想移植我的Java代码,您可以查看基于流的XMLWriter并使用libxml,因此它应该非常高效 .

  • 33

    您可以使用此方法:http://php.net/manual/en/function.htmlentities.php

    这样,所有实体(html / xml)都被转义,您可以将字符串放在XML标记中

  • 5

    根据sadeghj的解决方案,以下代码适用于我:

    /**
     * @param $arr1 the single string that shall be masked
     * @return the resulting string with the masked characters
     */
    function replace_char($arr1)
    {
        if (strpos ($arr1,'&')!== FALSE) { //test if the character appears 
            $arr1=preg_replace('/&/','&amp;', $arr1); // do this first
        }
    
        // just encode the
        if (strpos ($arr1,'>')!== FALSE) {
            $arr1=preg_replace('/>/','&gt;', $arr1);
        }
        if (strpos ($arr1,'<')!== FALSE) {
            $arr1=preg_replace('/</','&lt;', $arr1);
        }
    
        if (strpos ($arr1,'"')!== FALSE) {
            $arr1=preg_replace('/"/','&quot;', $arr1);
        }
    
        if (strpos ($arr1,'\'')!== FALSE) {
            $arr1=preg_replace('/\'/','&apos;', $arr1);
        }
    
        return $arr1;
    }
    
  • -1
    function replace_char($arr1)
     {
      $arr[]=preg_replace('>','&gt', $arr1); 
      $arr[]=preg_replace('<','&lt', $arr1);
      $arr[]=preg_replace('"','&quot', $arr1);
      $arr[]=preg_replace('\'','&apos', $arr1);
      $arr[]=preg_replace('&','&amp', $arr1);
    
      return $arr;
      }
    

相关问题