IT story

XML에서 CDATA 엔드 토큰을 이스케이프 처리하는 방법이 있습니까?

hot-time 2020. 7. 7. 07:31
반응형

XML에서 CDATA 엔드 토큰을 이스케이프 처리하는 방법이 있습니까?


]]>xml 문서의 CDATA 섹션 내에서 CDATA 종료 토큰 ( ) 을 이스케이프 처리하는 방법이 있는지 궁금합니다 . 또는 더 일반적으로 CDATA 내에서 사용하기위한 이스케이프 시퀀스가있는 경우 (그러나 존재하는 경우 어쨌든 시작 또는 종료 토큰을 이스케이프하는 것이 합리적이라고 생각합니다).

기본적으로 CDATA에 시작 또는 끝 토큰을 포함시키고 파서에게 해석하지 말고 다른 문자 시퀀스로 취급하도록 지시 할 수 있습니다.

아마 당신이 그것을하려고하면 XML 구조 또는 코드를 리팩터링해야하지만, 지난 3 년 동안 매일 xml을 사용해 왔지만이 문제가 없었습니다. 가능한지 궁금했습니다. 그냥 호기심.

편집하다:

HTML 인코딩을 사용하는 것 외에는 ...


분명히이 질문은 순수한 학문입니다. 다행히도 매우 명확한 답이 있습니다.

CDATA 종료 시퀀스를 이스케이프 할 수 없습니다. XML 사양 의 프로덕션 규칙 20 은 매우 분명합니다.

[20]    CData      ::=      (Char* - (Char* ']]>' Char*))

편집 :이 제품 규칙은 문자 그대로 "CData 섹션에는 원하는 순서로 ']]>'를 포함 할 수 있습니다. 예외는 없습니다."

EDIT2 : 같은 섹션 도 읽습니다.

CDATA 섹션 내에서 CDEnd 문자열 만 마크 업으로 인식되므로 왼쪽 꺾쇠 괄호와 앰퍼샌드가 리터럴 형식으로 나타날 수 있습니다. " <"및 " &"를 사용하여 이스케이프 할 필요는 없습니다 . CDATA 섹션은 중첩 할 수 없습니다.

다시 말해 엔터티 참조, 마크 업 또는 다른 형태의 해석 구문을 사용할 수 없습니다. CDATA 섹션 내에서 구문 분석 된 텍스트는 유일 ]]>하며 섹션을 종료합니다.

따라서 ]]>CDATA 섹션 내 에서 이스케이프 할 수 없습니다 .

EDIT3 : 같은 섹션 도 읽습니다.

2.7 CDATA 섹션

[정의 : CDATA 섹션은 문자 데이터가 발생할 수있는 모든 곳에서 발생할 수 있습니다. 이들은 마크 업으로 인식되는 문자를 포함하는 텍스트 블록을 이스케이프하는 데 사용됩니다. CDATA 섹션은 "<! [CDATA ["문자열로 시작하고 "]]>"문자열로 끝납니다.]

그러면 단일 CDATA 섹션 대신 여러 개의 인접한 CDATA 섹션을 포함하여 문자 데이터가 발생할 수있는 CDATA 섹션이있을 수 있습니다. 이를 통해 ]]>토큰 을 분할 하고 두 부분을 인접한 CDATA 섹션에 넣을 수 있습니다.

전의:

<![CDATA[Certain tokens like ]]> can be difficult and <invalid>]]> 

로 작성해야합니다

<![CDATA[Certain tokens like ]]]]><![CDATA[> can be difficult and <valid>]]> 

은닉하려면 데이터를 여러 조각으로 나눠야합니다 ]]>.

모든 것이 여기 있습니다 :

<![CDATA[]]]]><![CDATA[>]]>

첫 번째 <![CDATA[]]]]>]]입니다. 두 번째 <![CDATA[>]]>>입니다.


당신은 이스케이프하지 않지만 , 앞에 삽입 ]]>하여 >after 를 피하십시오. 이것은 C / Java / PHP / Perl 문자열과 같지만 a 전후에만 필요 합니다 .]]]]><![CDATA[>\>]]

BTW,

S.Lott의 대답은 이것과 동일합니다.


S. Lott의 대답은 맞습니다. 종료 태그를 인코딩하지 않고 여러 CDATA 섹션에서 분리합니다.

실제 환경에서이 문제를 해결하는 방법 : XML 편집기를 사용하여 컨텐츠 관리 시스템에 제공 할 XML 문서를 작성하려면 CDATA 섹션에 대한 기사를 작성하십시오. CDATA 섹션에 코드 샘플을 포함시키는 일반적인 트릭은 여기서 실패합니다. 내가 이것을 어떻게 배웠는지 상상할 수 있습니다.

그러나 대부분의 상황에서이 문제가 발생하지 않는 이유는 다음과 같습니다. XML 문서의 텍스트를 XML 요소의 내용으로 저장하려는 경우 DOM 메소드를 사용합니다. 예를 들면 다음과 같습니다.

XmlElement elm = doc.CreateElement("foo");
elm.InnerText = "<[CDATA[[Is this a problem?]]>";

그리고 DOM은 상당히 합리적으로 <와>를 이스케이프하므로 문서에 CDATA 섹션을 실수로 포함시키지 않았습니다.

아, 그리고 이것은 흥미 롭습니다 :

XmlDocument doc = new XmlDocument();

XmlElement elm = doc.CreateElement("doc");
doc.AppendChild(elm);

string data = "<![[CDATA[This is an embedded CDATA section]]>";
XmlCDataSection cdata = doc.CreateCDataSection(data);
elm.AppendChild(cdata);

This is probably an ideosyncrasy of the .NET DOM, but that doesn't throw an exception. The exception gets thrown here:

Console.Write(doc.OuterXml);

I'd guess that what's happening under the hood is that the XmlDocument is using an XmlWriter produce its output, and the XmlWriter checks for well-formedness as it writes.


simply replace ]]> with ]]]]><![CDATA[>


Here's another case in which ]]> needs to be escaped. Suppose we need to save a perfectly valid HTML document inside a CDATA block of an XML document and the HTML source happens to have it's own CDATA block. For example:

<htmlSource><![CDATA[ 
    ... html ...
    <script type="text/javascript">
        /* <![CDATA[ */
        -- some working javascript --
        /* ]]> */
    </script>
    ... html ...
]]></htmlSource>

the commented CDATA suffix needs to be changed to:

        /* ]]]]><![CDATA[> *//

since an XML parser isn't going to know how to handle javascript comment blocks


In PHP: '<![CDATA['.implode(explode(']]>', $string), ']]]]><![CDATA[>').']]>'


A cleaner way in PHP:

   function safeCData($string)
   {
      return '<![CDATA[' . str_replace(']]>', ']]]]><![CDATA[>', $string) . ']]>';
   }

Don't forget to use a multibyte-safe str_replace if required (non latin1 $string):

   function mb_str_replace($search, $replace, $subject, &$count = 0)
   {
      if (!is_array($subject))
      {
         $searches = is_array($search) ? array_values($search) : array ($search);
         $replacements = is_array($replace) ? array_values($replace) : array ($replace);
         $replacements = array_pad($replacements, count($searches), '');
         foreach ($searches as $key => $search)
         {
            $parts = mb_split(preg_quote($search), $subject);
            $count += count($parts) - 1;
            $subject = implode($replacements[$key], $parts);
         }
      }
      else
      {
         foreach ($subject as $key => $value)
         {
            $subject[$key] = mb_str_replace($search, $replace, $value, $count);
         }
      }
      return $subject;
   }

Another solution is to replace ]]> by ]]]><![CDATA[]>.


See this structure:

<![CDATA[
   <![CDATA[
      <div>Hello World</div>
   ]]]]><![CDATA[>
]]>

For the inner CDATA tag(s) you must close with ]]]]><![CDATA[> instead of ]]>. Simple as that.

참고URL : https://stackoverflow.com/questions/223652/is-there-a-way-to-escape-a-cdata-end-token-in-xml

반응형