【问题标题】:How to pass ä in xml using PHP如何使用 PHP 在 xml 中传递ä
【发布时间】:2015-08-12 09:11:46
【问题描述】:

我正在使用支付网关通过 CURL 发送 xml。使用 XML 验证器时出现以下错误:

XML 文档中的错误:实体“auml”被引用,但没有 声明。

所以我知道问题在于 ä,但是我不确定如何使用 PHP 解决此问题。

这是我传递的 xml 请求:

    <request type='payer-new' timestamp='XXXXXX'>
      <merchantid>XXXXXXXXX</merchantid>
      <orderid>XXXXXXXXX</orderid>
      <payer type='Business' ref='XXXXXXXXXXXXX'>                      
        <firstname>X&auml;xxxx</firstname>         
        <surname>x&auml;xxxxxx</surname>
        <address>
          <line1>XXXXXXXXXXXXX</line1>
          <line2>XXXXXXXXXXXXX</line2>
          <city>XXXXXXXXXXXXXXXX</city>
          <postcode>XXXXXXXXXXXX</postcode>
          <country code='FI'>Finland</country>
        </address>
        <phonenumbers>
          <home>XXXXXXXXXXXXXXXXXXXXXXXXX</home>
        </phonenumbers>
        <email>XXXXXXXXXXXXXXXXXXXXXXXXXXXXX</email>
      </payer>                       
      <sha1hash>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</sha1hash>
    </request>

我将 htmlentities 包裹在进入请求的所有变量周围,如下所示:

".htmlentities($_SESSION['W_CUSTOMER_FIRSTNAME'], ENT_QUOTES, “UTF-8”)。”

有没有一种方法可以处理包含这些字符的各种字符/名称/地点等?

在此先感谢

【问题讨论】:

  • 不要使用htmlentities,而是使用htmlspecialchars
  • 谢谢,我试试这个
  • 从技术上讲,您对该函数使用了错误的参数。请参阅该函数的 ENT_XML1 标志。但还有更多,我留下的答案给了你另一个建议。

标签: php xml


【解决方案1】:

&amp;auml; 是 HTML 实体代码,而不是通用 XML 代码。

通用 XML 只能理解三个命名实体:&amp;amp;&amp;gt;&amp;lt;

如果您想使用任何其他命名实体,例如&amp;auml;,则必须在 XML 模式定义中定义这些实体。一些标准化的 XML 方言具有定义命名实体的模式,但大多数没有,如果您没有模式,那么您肯定无法使用任何命名实体。

因此,与其在 XML 中使用命名实体,不如使用数字实体通常更好。它们采用&amp;#1234; 的形式,其中1234 是您想要的字符的字符代码。对于 auml 字符,您需要的代码是 &amp;#228;。请注意,这些数字实体代码也可以在 HTML 中正常工作。

您可以在此处找到一些更有用的字符代码列表:http://www.econlib.org/library/asciicodes.html

令人讨厌的是,没有标准的 PHP 函数可以生成这些数字 XML 实体。 htmlentities()html_special_chars() 函数不合适,因为它们会生成命名实体。所以我们必须自己写。

您需要使用ord() 函数来获取字符代码,但要注意多字节字符。实际上,the manual page for htmlentities() 上的 cmets 中的 xmlentities() 函数有一个合理的尝试,您可以尝试。不过,我知道还有其他实现。

【讨论】:

  • 谢谢,这很有道理
  • > 不过,我知道存在其他实现。请也与我们分享。提到的 xmlentities() 函数在多字节字符上确实失败了。
【解决方案2】:

根本问题是您有一个使用 HTML 实体对事物进行编码的 XML 文档。 XML Validator 对特定于 HTML 的实体一无所知,因此会窒息。

我希望 XML 有一个 XSD(模式);它确实应该在根标记中使用 xmlns 声明进行声明,也可能使用 xsi:schemaLocation 进行声明。这个 XSD 文件将是 xsd:import html 实体的正确位置,这将使您的验证器能够正确验证。还应该有一个 标记作为第一行。

也就是说,我怀疑接收应用程序不会关心验证器说什么,并且假设接收器也知道 html 实体,您的响应文件可能还不错。

如果不是,您需要将 html 实体解码为实际的 utf8 字符,但可能只在 DOM 的文本元素上这样做(例如, 的内容而不是整个文本)。使用 php 的 html_entity_decode() 执行此操作似乎是合理的。如果你这样做,你肯定需要标签来包含文件字符集。

HTH

【讨论】:

  • 谢谢。我将尝试解码选项,并让您知道我的进展情况。我只是将 xml 传递给 CURL,所以应该很简单。大多数数据都正确传递,只是这些字符给了我一个错误。
【解决方案3】:

我将 htmlentities 包裹在进入请求的所有变量周围,如下所示:...

你的问题。您正在“手动”创建 XML 字符串。并不是说不能这样做,只是这样做很容易出错。一个提示可能是您已经使用的函数的名称,它以“html”开头,它不是 XML

无论如何,在深入讨论内插字符串在哪些范围内可能会导致创建 XML 的麻烦以及出现此类问题时,使用 XML 库来创建 XML 会容易得多。

XML 库允许您正确编码所有数据(因此您不会看到此类错误)并且很容易。在 PHP 中通常有三个:

  • SimpleXML
  • DOM
  • XMLWriter

选择最适合你的。

或者,您可以使用以下 XML 库之一验证您“手动”创建的 XML 格式是否正确您将其发送到远程服务,因为它们也是 XML解析器:

  • SimpleXML
  • DOM

本网站上已经存在关于如何使用其中任何一种创建 XML 文档的问答材料——即使上面有示例和 cmets——所以我不会在我的回答中重复这些内容。 XML 验证也是如此。


设置了一些参数的请求的 XML 预设(模式)示例。这里有 SimpleXML

$pattern = <<<REQUEST_PATTERN
<request type='payer-new' timestamp='XXXXXX'>
    <merchantid>XXXXXXXXX</merchantid>
    <orderid>XXXXXXXXX</orderid>
    <payer type='Business' ref='XXXXXXXXXXXXX'>
        <firstname></firstname>
        <surname></surname>
        <address>
            <line1>XXXXXXXXXXXXX</line1>
            <line2>XXXXXXXXXXXXX</line2>
            <city>XXXXXXXXXXXXXXXX</city>
            <postcode>XXXXXXXXXXXX</postcode>
            <country code='FI'>Finland</country>
        </address>
        <phonenumbers>
            <home>XXXXXXXXXXXXXXXXXXXXXXXXX</home>
        </phonenumbers>
        <email>XXXXXXXXXXXXXXXXXXXXXXXXXXXXX</email>
    </payer>
    <sha1hash>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</sha1hash>
</request>
REQUEST_PATTERN;

$xml = simplexml_load_string($pattern);
$xml->payer->firstname = 'Äpfel';
$xml->payer->surname = 'Wachsen-Überirdisch';

# ...

// just an assumed way on how you would pass the XML string
// to the API via CURL (here as HTTP POST request body)
curl_setopt($handle, CURLOPT_POSTFIELDS, $xml->asXML());

将传递给远程服务的 XML 将始终 (*) 以适当的方式进行 XML 编码:

<?xml version="1.0"?>
<request type="payer-new" timestamp="XXXXXX">
    <merchantid>XXXXXXXXX</merchantid>
    <orderid>XXXXXXXXX</orderid>
    <payer type="Business" ref="XXXXXXXXXXXXX">
        <firstname>&#xC4;pfel</firstname>
        <surname>Wachsen-&#xDC;berirdisch</surname>
        <address>
            <line1>XXXXXXXXXXXXX</line1>
            <line2>XXXXXXXXXXXXX</line2>
            <city>XXXXXXXXXXXXXXXX</city>
            <postcode>XXXXXXXXXXXX</postcode>
            <country code="FI">Finland</country>
        </address>
        <phonenumbers>
            <home>XXXXXXXXXXXXXXXXXXXXXXXXX</home>
        </phonenumbers>
        <email>XXXXXXXXXXXXXXXXXXXXXXXXXXXXX</email>
    </payer>
    <sha1hash>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</sha1hash>
</request>

(*) 在极少数情况下情况并非如此,但它们不应在此示例中发挥任何作用:SimpleXML 库需要正确的 UTF-8 编码字符串才能工作。

【讨论】:

  • 这听起来很有帮助。我会试一试,让你知道我的进展情况
【解决方案4】:

我为 XML 字符串安全替换创建了这样的函数:

     /**
     * Safe symbols escaping for XML. It's very similar to htmlspecialschars for html + mysql.
     * @param string $string
     * @return string
     */
    public static function xmlentities(string $string): string
    {
        return  htmlspecialchars($string, ENT_XML1, 'UTF-8', true);
    }

用法:

        $str = 'Dafür hörten "der Relativen Schw&amp;auml;che&amp;ldquo;-Entwicklung gegen&amp;uuml;ber den Wall Street';
        $str = static::xmlentities($str);
        echo '<?xml version="1.0" encoding="UTF-8"?>
            <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
            <set>'.$str.'</set>
            </urlset>';

说明:

  • ENT_XML1 设置为 XML 文档接受的符号列表
  • 'UTF-8' 设置字符集,因此 ä 和其他德国/国家符号被接受为符号
  • true -- 最后一个 TRUE 参数使得转换安全罪孽它经常发生传入字符串已经有一些 htmlspecialchars 进位符号(例如,在从 DB 加载或从 API 获取期间)

记得把字符集声明放到文档头

<?xml version="1.0" encoding="UTF-8"?>

或为 htmlspecialchars 设置一些其他字符集

【讨论】:

    【解决方案5】:

    我遇到了同样的问题,我已经解决了问题。

    $str = 'Dafür hörten "der Relativen Schw&amp;auml;che&amp;ldquo;-Entwicklung gegen&amp;uuml;ber den Wall Street';
    
    echo htmlspecialchars($str, ENT_XML1, 'UTF-8', true);
    

    我希望,这是有用的,它正在工作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-11
      • 1970-01-01
      • 2015-03-30
      • 2011-04-03
      • 1970-01-01
      • 2014-02-28
      • 1970-01-01
      • 2019-09-15
      相关资源
      最近更新 更多