자바스크립트 코드 내에서 & 기호를 XML 엔터티인 &로 변경하는 문제

자바스크립트 코드 내에서 & 기호를 XML 엔터티인 &로 변경하는 문제

1 . 문제는 뭐지

정상적인 코드인데 파서라는 녀석은 이것을 에러로 알아본단 말이야, 그럼 어떻게 할까요?
'&&'기호를 어떻게 해석하게 하느냐의 문제군요!  늘 궁금했는데...

답: 블록 안에 넣어 파서가 내용을 무시하도록한다.



주어진 이미지와 에러 메시지를 보니, 블로그스팟 테마의 HTML 편집 시 발생하는 org.xml.sax.SAXParseException 에러는 HTML 특수 문자 처리가 원인입니다.

2. 문제의 원인

블로그스팟 테마 편집기는 XML 기반의 HTML을 사용합니다. 이 환경에서는 & 기호가 XML 엔터티 참조의 시작을 의미하므로, 단순히 <div class="some-class & another-class"> 와 같이 사용하면 구문 오류가 발생합니다.

이미지에서 에러가 발생한 117번째 줄을 보면 다음과 같은 코드가 있습니다.

JavaScript
if (mainTitle && mainTitle.nextSibling) {

이 코드는 <b:include data='blog' name='all-head-content'/> 와 같은 블로그스팟의 특별한 태그(XML)와 혼합될 때 문제가 발생할 수 있습니다. 자바스크립트 코드 내의 && 연산자가 XML 파서에게 &로 시작하는 엔티티 참조로 오해를 받기 때문입니다.

3. 해결책

자바스크립트 코드 내에서 & 기호를 XML 엔터티인 &amp;로 변경해주면 됩니다. 하지만, 자바스크립트 코드 자체를 변경하는 것보다 더 안전하고 쉬운 방법은 HTML과 자바스크립트 코드를 <![CDATA[...]]> 블록 안에 넣어 파서가 내용을 무시하도록 하는 것입니다.

아래는 수정된 코드입니다. 이 코드는 XML 파서가 자바스크립트 코드를 XML이 아닌 일반 텍스트로 인식하게 만들어줍니다.

3-1. 블로그스팟 테마용 수정 코드 (에러 해결)

1. HTML 편집기로 이동

블로그스팟 대시보드에서 '테마' > **'HTML 편집'**으로 이동합니다.

2. JavaScript 코드 수정

기존에 삽입하셨던 <script> 태그를 찾아 아래와 같이 수정합니다.

HTML
<script>
//<![CDATA[
document.addEventListener('DOMContentLoaded', function() {
    const mainBody = document.querySelector('data:post.body');
    const mainTitle = document.querySelector('h1.post-title');

    const tocContainer = document.createElement('div');
    tocContainer.className = 'toc-container';

    const tocTitle = document.createElement('h2');
    tocTitle.className = 'toc-title';
    tocTitle.innerHTML = '목차 <span class="toggle-icon">▼</span>';
    
    const tocContent = document.createElement('div');
    tocContent.className = 'toc-content';
    
    const tocList = document.createElement('ul');
    tocList.id = 'toc-list';
    
    const headers = document.querySelectorAll('h2, h3');
    
    if (headers.length > 0) {
        headers.forEach((header, index) => {
            const headerId = 'toc-' + index;
            header.id = headerId;
            
            const li = document.createElement('li');
            li.innerHTML = `<a href="#${headerId}">${header.innerText}</a>`;
            if (header.tagName.toLowerCase() === 'h2') {
                li.className = 'toc-h2';
            } else if (header.tagName.toLowerCase() === 'h3') {
                li.className = 'toc-h3';
            }
            tocList.appendChild(li);
        });
        
        tocContent.appendChild(tocList);
        tocContainer.appendChild(tocTitle);
        tocContainer.appendChild(tocContent);
        
        // 목차를 게시글 제목 바로 아래에 삽입
        if (mainTitle && mainTitle.nextSibling) {
            mainTitle.parentNode.insertBefore(tocContainer, mainTitle.nextSibling);
        } else if (mainBody) {
            mainBody.parentNode.insertBefore(tocContainer, mainBody);
        }
        
        // 목차 접기/펼치기 기능 추가
        tocTitle.addEventListener('click', function() {
            const isHidden = tocContent.style.display === 'none' || tocContent.style.display === '';
            tocContent.style.display = isHidden ? 'block' : 'none';
            
            const toggleIcon = this.querySelector('.toggle-icon');
            toggleIcon.innerText = isHidden ? '▲' : '▼';
        });
    }
});
//]]>
</script>

수정된 부분: <script> 태그의 시작과 끝에 //<![CDATA[**와 **//]]>를 추가했습니다. 이 블록은 XML 파서에게 "이 안의 내용은 XML 구문이 아니라 일반 텍스트이므로 문법 검사를 하지 마라"고 지시하는 역할을 합니다. 이렇게 하면 &와 같은 특수 문자가 에러를 일으키는 것을 방지할 수 있습니다.

파서가 궁금하지는 않는거조!!

파서는 뭐지?

3. 요약

요약하면,  에러가 발생했던 && 연산자 자체를 수정하는 것보다, 자바스크립트 코드 블록 전체를 <![CDATA[]]>로 감싸는 것이 더 안전하고 간편한 해결책입니다. 이 방법으로 에러를 해결하고 원하는 목차 기능을 구현할 수 있습니다.

처음으로 

0 Comments:

댓글 쓰기