Programing

문자열을 "XML 안전"으로 만드는 방법은 무엇입니까?

lottogame 2020. 12. 7. 07:41
반응형

문자열을 "XML 안전"으로 만드는 방법은 무엇입니까?


PHP 에코를 통해 XML 문서를 보내 AJAX 호출에 응답하고 있습니다. 이 XML 문서를 구성하기 위해 데이터베이스 레코드를 반복합니다. 문제는 데이터베이스에 '<'기호가있는 레코드가 포함되어 있다는 것입니다. 따라서 당연히 브라우저는 특정 지점에서 오류를 발생시킵니다. 이 문제를 어떻게 해결할 수 있습니까?


를 사용하여 해당 문자를 이스케이프 htmlspecialchars하거나 더 적절하게 DOMDocument 또는 XMLWriter 와 같은 XML 문서를 빌드하기위한 라이브러리를 사용합니다 .

또 다른 대안은 CDATA 섹션을 사용하는 것이지만 ]]>.

또한 XML 문서에 대해 정의한 인코딩 (기본적으로 UTF-8)을 준수해야한다는 점도 고려하십시오.


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에 대한 수동 항목을 참조하십시오 .


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

이 시도:

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

따라서 htmlentities()함수를 사용하여 데이터를 필터링 한 후 다음 과 같은 XML 태그의 데이터를 사용할 수 있습니다.

<mytag>$str</mytag>

가능하다면 항상 문자열 조작보다는 XML 클래스를 사용하여 XML을 생성하는 것이 좋습니다. 클래스가 필요에 따라 자동으로 문자를 이스케이프한다는 이점 중 하나입니다.


누군가를 돕는 경우에 이것을 추가하십시오.

일본어 문자로 작업하면서 인코딩도 적절하게 설정되었습니다. 그러나 때때로, 나는 그것을 발견 htmlentities하고 htmlspecialchars충분하지 않다.

일부 사용자 입력에는 위의 기능으로 제거되지 않은 특수 문자가 포함되어 있습니다. 이 경우 다음을 수행해야합니다.

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

이것은 또한 또는 xml-unsafe같은 특정 제어 문자를 제거 합니다. 사용 하여 생략 할 문자를 결정할 수 있습니다 .Null characterEOT


나는 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가 필요 하거나 다른 폴리 필로 교체해야하지만이 함수는 우리에게 잘 작동합니다!

궁금한 사람을 위해 관련 Go 소스 https://golang.org/src/encoding/xml/xml.go?s=44219:44263#L1887

참고 URL : https://stackoverflow.com/questions/3426090/how-do-you-make-strings-xml-safe

반응형