1. 최상위에 DTD 선언한다.
1.0 transitional의 경우 : <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 1.0 strict의 경우 : <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 1.1의 경우 : <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2. html:html을 사용한다.
<html:html xhtml="true"> ... </html:html>
이것은 다음과 같이 변환되며
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
html:text 등의 사용시 다음과 같이 명시적으로 태그를 닫아주게 된다.
<input type="text" ... />
이때 html의 lang attribute는 backword compatible만을 위해 존재하며 XHTML 1.1에서는 제거되도록 명시되어있기 때문에 validator에서 문제가 된다.
struts의 xhtml은 현재 1.0을 지원한다. 참고
따라서 간단한 해결책은 1.0 수준에서 검증하거나, 아래와 같이 html을 수동 구현 하는 것이다.
struts의 xhtml은 현재 1.0을 지원한다. 참고
따라서 간단한 해결책은 1.0 수준에서 검증하거나, 아래와 같이 html을 수동 구현 하는 것이다.
<html:xhtml /> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US"> 혹은 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko-KR"> ...
html:xhtml 태그를 이용한 선언으로 위의 input 박스 등의 문제는 모두 해결할 수 있다.
3. url 사용시
<a href="/blog/comment.do?id=mmx900&articleId=12&commentId=3">이와 같은 url은
- cannot generate system identifier for general entity "articleId"
- general entity "method" not defined and no default entity
- reference not terminated by REFC delimiter
- reference to external entity in attribute value
ISO 표준에 따라 이들 &을 & a m p ;로 변환해야 하는데, jstl core 태그 라이브러리의 url은 기본으로 &을 넣어 생성한다.
이 URL을 c:out을 이용하면 & a m p ;로 변환되어 출력되지만, 달리 이용할 경우(ex: html:link나 html:form에 사용할 경우) 일일이 ${fn:escapeXml(param)}을 써 주는 수 밖에는 방법이 없다.
(문서에 따라 c:url은 자동으로 앰퍼샌드를 변환한다고도 되어 있던데 여하간 1.1.2의 jakarta taglibs standards에선 지원 안된다.)
일괄적으로, 다음과 같이 정의할수도 있다.
이 URL을 c:out을 이용하면 & a m p ;로 변환되어 출력되지만, 달리 이용할 경우(ex: html:link나 html:form에 사용할 경우) 일일이 ${fn:escapeXml(param)}을 써 주는 수 밖에는 방법이 없다.
(문서에 따라 c:url은 자동으로 앰퍼샌드를 변환한다고도 되어 있던데 여하간 1.1.2의 jakarta taglibs standards에선 지원 안된다.)
일괄적으로, 다음과 같이 정의할수도 있다.
<c:url var="url_blog_rss" value="blog" scope="request"> <c:param name="id" value="${param.id}" /> <c:param name="method" value="rss" /> </c:url> <c:set var="url_blog_rss" value="${fn:escapeXml(url_blog_rss)}" scope="request"/>변수를 정의할 때 c:url과 c:set의 scope 를 동일하게 해 주는 것을 잊지 말자. 아무런 에러를 내지 않아도 서로 다른 결과가 나올 수 있다.
추가적인 문제해결 ¶
validator에서 다음과 같은 에러가 나올때는 황당하기 짝이 없다.
Line 136, column 6: end tag for "head" which is not finished </head> Most likely, You nested tags and closed them in the wrong order. For example <p><em>...</p> is not acceptable, as <em> must be closed before <p>. Acceptable nesting is: <p><em>...</em></p> Another possibility is that you used an element (e.g. 'ul') which requires a child element (e.g. 'li') that you did not include. Hence the parent element is "not finished", not complete.
이때는 head 안에 title 태그를 넣어준다. 참고 : 'end tag for "HEAD" which is not finished' Error if has no
form name도 문제다. xhtml 1.1에서는 모든 id가 name 속성을 대체한다.
Line 144, column 13: there is no attribute "name" <form name="userForm" method="post" action="/blogHaja/user.do;jsessionid=29841 ...
여기를 참고하여 패치하거나 스트러츠의 다음 버전이 나오는 수 밖에 없는 듯 하다.