web-dev-qa-db-ja.com

文字列を「XML safe」にする方法は?

AJAX呼び出しに応答しています。PHP echosを介してXMLドキュメントを送信します。このXMLドキュメントを作成するために、データベース:問題は、データベースに「<」記号が含まれているレコードが含まれていることです。

57
JayD3e

これらの文字を htmlspecialchars でエスケープするか、おそらくより適切に、 DOMDocumentXMLWriter

もう1つの方法はCDATAセクションを使用することですが、]]>の出現を探す必要があります。

また、XMLドキュメントに対して定義するエンコード(デフォルトではUTF-8)を尊重する必要があることも考慮してください。

62
Artefacto

PHP 5.4から使用できます:

htmlspecialchars($string, ENT_XML1);

次のようなエンコーディングを指定する必要があります。

htmlspecialchars($string, ENT_XML1, 'UTF-8');

更新

上記は変換のみを行うことに注意してください:

  • &から&amp;
  • <から&lt;
  • >から&gt;

二重引用符で囲まれた属性で使用するためにテキストをエスケープする場合:

htmlspecialchars($string, ENT_XML1 | ENT_COMPAT, 'UTF-8');

"&quot;、および&に加えて、<>に変換します。


そして、属性が単一引用符で囲まれている場合:

htmlspecialchars($string, ENT_XML1 | ENT_QUOTES, 'UTF-8');

'&apos;&、および<に加えて、>"に変換します。

(もちろん、これは属性の外でも使用できます)。


htmlspecialcharsの手動エントリ を参照してください。

59
user3409662

1)次のようにテキストをCDATAとしてラップできます。

<mytag>
    <![CDATA[Your text goes here. Btw: 5<6 and 6>5]]>
</mytag>

http://www.w3schools.com/xml/xml_cdata.asp を参照してください

2)すでに誰かが言ったように:それらの文字をエスケープします。例えば。そのようです:

5&lt;6 and 6&gt;5
9
Elvith

これを試して:

_$str = htmlentities($str,ENT_QUOTES,'UTF-8');
_

したがって、htmlentities()関数を使用してデータをフィルタリングした後、XMLタグのデータを次のように使用できます。

_<mytag>$str</mytag>
_
5
Mosiur

可能な場合は、文字列操作ではなくXMLクラスを使用してXMLを作成することをお勧めします。利点の1つは、クラスが必要に応じて文字を自動的にエスケープすることです。

5
Ed Schembor

誰かを助けるためにこれを追加します。

私は日本語の文字を扱っているため、エンコードも適切に設定されています。しかし、時々、htmlentitieshtmlspecialcharsでは不十分であることがわかります。

一部のユーザー入力には、上記の機能によって削除されない特殊文字が含まれています。それらの場合、私はこれをしなければなりません:

preg_replace('/[\x00-\x1f]/','',htmlspecialchars($string))

これにより、xml-unsafeEOTなどの特定のNull character制御文字も削除されます。この table を使用して、除外する文字を決定できます。

4
Reuben L.

GolangがXMLのエスケープを引用する方法(および改行エスケープやその他の文字のエスケープなど)を好むので、XMLエスケープ関数をPHP以下に移植しました

function isInCharacterRange(int $r): bool {
    return $r == 0x09 ||
            $r == 0x0A ||
            $r == 0x0D ||
            $r >= 0x20 && $r <= 0xDF77 ||
            $r >= 0xE000 && $r <= 0xFFFD ||
            $r >= 0x10000 && $r <= 0x10FFFF;
}

function xml(string $s, bool $escapeNewline = true): string {
    $w = '';

    $Last = 0;
    $l = strlen($s);
    $i = 0;

    while ($i < $l) {
        $r = mb_substr(substr($s, $i), 0, 1);
        $Width = strlen($r);
        $i += $Width;
        switch ($r) {
            case '"':
                $esc = '&#34;';
                break;
            case "'":
                $esc = '&#39;';
                break;
            case '&':
                $esc = '&amp;';
                break;
            case '<':
                $esc = '&lt;';
                break;
            case '>':
                $esc = '&gt;';
                break;
            case "\t":
                $esc = '&#x9;';
                break;
            case "\n":
                if (!$escapeNewline) {
                    continue 2;
                }
                $esc = '&#xA;';
                break;
            case "\r":
                $esc = '&#xD;';
                break;
            default:
                if (!isInCharacterRange(mb_ord($r)) || (mb_ord($r) === 0xFFFD && $Width === 1)) {
                    $esc = "\u{FFFD}";
                    break;
                }

                continue 2;
        }
        $w .= substr($s, $Last, $i - $Last - $Width) . $esc;
        $Last = $i;
    }
    $w .= substr($s, $Last);
    return $w;
}

mb_ordの使用のために少なくともPHP7.2が必要であることに注意してください。または、別のポリフィルと交換する必要がありますが、これらの関数はうまく機能しています。

好奇心anyone盛な人のために、関連するGoソースを次に示します https://golang.org/src/encoding/xml/xml.go?s=44219:44263#L1887

0
Brian Leishman