XML과 HTML을 정규식으로 구문 분석하기 어려운 이유에 대한 몇 가지 예를 제공 할 수 있습니까? [닫은]


402

하나의 실수 나는 사람들이 만드는 참조 이상다시 정규식으로 XML 또는 HTML을 구문 분석을 시도하고 있습니다. XML과 HTML을 파싱하는 것이 어려운 몇 가지 이유는 다음과 같습니다.

사람들은 파일을 일련의 행으로 취급하려고하지만 유효합니다.

<tag
attr="5"
/>

사람들은 <또는 <tag를 태그의 시작으로 취급하기를 원하지만 다음과 같은 것들이 야생에 존재합니다.

<img src="imgtag.gif" alt="<img>" />

사람들은 종종 시작 태그와 끝 태그를 일치 시키려고하지만 XML과 HTML을 사용하면 태그에 자신을 포함시킬 수 있습니다 (전통적인 정규 표현식은 전혀 처리 할 수 ​​없음).

<span id="outer"><span id="inner">foo</span></span> 

사람들은 종종 문서의 내용 (예 : 유명한 "주어진 페이지에서 모든 전화 번호 찾기"문제)과 일치하기를 원하지만 데이터가 표시 될 때 데이터가 표시 될 수 있습니다 (보았을 때 정상으로 보이는 경우에도).

<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>

주석에 형식이 잘못되었거나 불완전한 태그가 포함될 수 있습니다.

<a href="foo">foo</a>
<!-- FIXME:
    <a href="
-->
<a href="bar">bar</a>

다른 어떤 문제를 알고 있습니까?


14
웹 브라우저는 이러한 종류의 혼란을 초당 수백만 번 이해합니다. 누군가가 단순한 필사자를 위해 웹 페이지 파서 클래스를 만들 수 없습니까?
Jon Winstanley

24
존. Perl에는 많은 HTML :: Parser, HTML :: TreeBuilder 등이 있습니다.
Chas. Owens

12
가장 좋은 대답은 stackoverflow.com/a/1732454/135078입니다 (Zalgo주의)
Kelly S. French

3
[정규식으로 [X] HTML을 구문 분석 할 수없는 이유] [1] [1] : stackoverflow.com/a/1732454/468725
Pavel P

4
여기 당신이 방법의 좋은 설명 확실하게 할 수 있습니다 패턴 구문 분석 HTML 뿐만 아니라, 왜 같은 당신은 아마 그렇게하지 않으려는.
tchrist

답변:


260

다음은 유용한 XML을 보여줍니다.

<!DOCTYPE x [ <!ENTITY y "a]>b"> ]>
<x>
    <a b="&y;>" />
    <![CDATA[[a>b <a>b <a]]>
    <?x <a> <!-- <b> ?> c --> d
</x>

그리고이 작은 기쁨 묶음은 유효한 HTML입니다.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" [
    <!ENTITY % e "href='hello'">
    <!ENTITY e "<a %e;>">
]>
    <title>x</TITLE>
</head>
    <p id  =  a:b center>
    <span / hello </span>
    &amp<br left>
    <!---- >t<!---> < -->
    &e link </a>
</body>

유효하지 않은 구문에 대한 모든 브라우저 별 구문 분석은 말할 것도 없습니다.

행운을 빕니다.

편집 (Jörg W Mittag) : 다음은 잘 구성된 유효한 HTML 4.01의 또 다른 멋진 부분입니다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd"> 
<HTML/
  <HEAD/
    <TITLE/>/
    <P/>

6
XML 하나? 거기에 몇 가지 다른 구성이 있는데, 문제가 있습니까? DTD 내부 하위 집합? 그것은 새로운 & 엔터티를 정의하고 있습니다; 일반적으로 따옴표가 아닌 경우 내부 하위 집합을 종료하는 ']>'시퀀스를 포함하는 'y'라고합니다.
bobince

16
(이것은 DTD 유효성 검사 파서가 아닌 경우에도 문서를 올바르게 구문 분석하기 위해 XML의 좀 더 난해하고 고풍스러운 DTD 기능에 대해 상당히 깊이 알고 있어야 함을 보여줍니다.)
bobince

17
HTML 예제는 드물게 알려진 기능인 shorttags를 사용합니다. w3.org/QA/2007/10/shorttags.html
netvope

25
위와 같이 HTML을 작성할 때마다 Tim Berners-Lee는 단 한 번의 눈물을 흘립니다.
fgysin reinstate Monica

5
"]"의 첫 번째 발생에서 Stackoverflow의 구문 형광펜이 실패하는 방식이 마음에 듭니다.
GlassGhost

71

사실은

<img src="imgtag.gif" alt="<img>" />

유효한 HTML이 아니며 유효한 XML도 아닙니다.

'<'및 '>'는 속성 문자열 내에서 유효한 문자가 아니므로 유효한 XML이 아닙니다. 해당 XML 엔티티를 사용하여 이스케이프해야합니다. & lt; & gt;

HTML에서 짧은 닫기 양식이 허용되지 않기 때문에 유효한 HTML이 아닙니다 (XML 및 XHTML에서는 정확함). 'img'태그는 HTML 4.01 사양에 따라 암시 적으로 닫힌 태그이기도합니다. 즉, 수동으로 닫는 것은 실제로 잘못되었으며 다른 태그를 두 번 닫는 것과 같습니다.

HTML의 올바른 버전은

<img src="imgtag.gif" alt="&lt;img&gt;">

XHTML과 XML의 올바른 버전은

<img src="imgtag.gif" alt="&lt;img&gt;"/>

다음 예제도 유효하지 않습니다.

<
tag
attr="5"
/>

이것은 유효한 HTML 또는 XML도 아닙니다. 속성과 닫는 '>'는 원하는 위치에있을 수 있지만 태그 이름은 '<'바로 뒤에 있어야합니다. 유효한 XML은 실제로

<tag
attr="5"
/>

그리고 여기 또 하나 더 펑키 한 것이 있습니다 : 실제로 "또는"를 속성 인용 문자로 사용하도록 선택할 수 있습니다

<img src="image.gif" alt='This is single quoted AND valid!'>

게시 된 다른 모든 이유는 정확하지만 HTML 구문 분석의 가장 큰 문제는 사람들이 일반적으로 모든 구문 규칙을 올바르게 이해하지 못한다는 것입니다. 브라우저가 태그를 HTML로 해석한다고해서 실제로 유효한 HTML을 작성한 것은 아닙니다.

편집 : 심지어 stackoverflow.com도 유효하고 유효하지 않은 정의에 대해 동의합니다. 수정 된 버전이있는 동안 잘못된 XML / HTML이 강조 표시되지 않습니다.

기본적으로 XML은 정규 표현식으로 구문 분석되지 않습니다. 그러나 그렇게 할 이유도 없습니다. 각 언어마다 많은 XML 파서가 있습니다. SAX 파서, DOM 파서 및 풀 파서 중에서 선택할 수 있습니다. 이 모든 것이 정규 표현식으로 구문 분석하는 것보다 훨씬 빠르므로 결과 DOM 트리에서 XPath 또는 XSLT와 같은 멋진 기술을 사용할 수 있습니다.

따라서 내 대답은 다음과 같습니다. 정규 표현식으로 XML을 구문 분석하는 것뿐만 아니라 나쁜 생각이기도합니다. 수백만 개의 기존 XML 파서 중 하나를 사용하고 XML의 모든 고급 기능을 활용하십시오.

HTML은 너무 직접 구문 분석을 시도하기가 너무 어렵습니다. 첫째, 법적인 구문에는 당신이 알지 못하는 작은 미묘함이 많이 있으며, 두 번째로, 야생의 HTML은 엄청난 양의 더미입니다 (내가 표류하게됩니다). 태그 수프와 같은 HTML을 잘 처리하는 다양한 lax 파서 라이브러리가 있습니다.이를 사용하십시오.


8
> as>를 벗어날 필요는 없습니다.
Joey

8
좋아요, s / valid /는 wild / g
Chas에 있습니다. Owens

1
실제로, 사양에 따라 <as <& and & amp; 속성은 ""& ","& apos; 속성은 그저 많은 파서 일뿐입니다.
LordOfThePigs

19
사양에서 '>'는 이스케이프해야한다고 말하지 않습니다. 내용에서 '']]> '시퀀스의 특수한 경우는 예외입니다. 이러한 이유로 항상 '>'를 이스케이프하는 것이 가장 쉽지만 사양에는 필요하지 않습니다.
bobince

8
>기호는 HTML에서 완벽하게 유효 stackoverflow.com/questions/94528/...
JFS

56

이 주제에 관한 전체 블로그 항목을 작성했습니다 : 정규식 제한

문제의 핵심은 HTML과 XML이 재귀 구조이므로 제대로 구문 분석하기 위해 계산 메커니즘이 필요하다는 것입니다. 진정한 정규 표현식은 계산할 수 없습니다. 계산하려면 컨텍스트 프리 문법이 있어야합니다.

이전 단락에는 약간의 경고가 있습니다. 특정 정규식 구현은 이제 재귀 개념을 지원합니다. 그러나 정규 표현식에 재귀를 추가하기 시작하면 경계가 실제로 확장되고 파서를 고려해야합니다.


20

목록에없는 한 가지는 속성이 어떤 순서로나 나타날 수 있다는 것입니다. 따라서 정규 표현식이 href "foo"및 클래스 "bar"와의 링크를 찾으려면 순서에 관계없이 다른 수를 가질 수 있습니다 그들 사이의 것들.


아, 그렇습니다.이 질문 (첫 번째 링크)을 요구하는 질문조차있었습니다.
Chas. Owens

16

"구문 분석"의 의미에 따라 다릅니다. 일반적으로 XML 문법은 결코 정규적이지 않기 때문에 정규식을 사용하여 XML을 구문 분석 할 수 없습니다. 간단히 말해서, 정규 표현식은 셀 수 없습니다 (물론, Perl 정규 표현식은 실제로 계산할 수 있습니다).


역 참조가 오픈 태그와 클로즈 태그의 문제를 해결할 수 있다고 생각합니다.
Rishul Matta

1
@RishulMatta : 어떻게 요? 역 참조 횟수가 제한되어 있으며 태그를 역으로 바꿔야한다는 점에 유의하십시오. 또한 정규식의 엄격한 정의는 역 참조를 허용하지 않습니다.
Willem Van Onsem 2016 년

.NET은 팝 및 푸시 식의 균형을 조정할 수 있으며 이론적으로 계층 구조를 일치시키는 데 사용할 수 있습니다. 그러나 여전히 나쁜 생각입니다.
Abel

9

사람들은 실제로 정규 표현식을 사용하여 실수를 저지르고 있습니까? 아니면 그들이 달성하려는 작업에 충분합니까?

다른 사람들이 대답 했으므로 정규식을 사용하여 html 및 xml을 구문 분석 할 수 없다는 것에 전적으로 동의합니다.

그러나 요구 사항이 html / xml을 구문 분석하지 않고 html / xml의 "알려진"비트에서 하나의 작은 비트의 데이터를 얻는 것이라면 정규식 또는 심지어 더 간단한 "하위 문자열"로 충분합니다.


7
"충분히 좋다"고 정의하십시오. 필연적으로 간단한 정규식이 작동하지 않습니다. 버그와 일치하지 않는 것과 일치하지 않습니까? 그렇다면 정규 표현식을 사용하는 것은 실수입니다. HTML 및 XML 파서는 사용하기 어렵지 않습니다. 그것들을 배우지 않는 것은 잘못된 경제입니다.
Chas. Owens

1
좋아, "충분히 좋은"을 정의하십시오. 클라이언트 IP 주소를 알려주는 웹 페이지가 있다고 가정 해 보겠습니다. 그게 다야. 이제 클라이언트 컴퓨터의 IP 주소를 알려주는 응용 프로그램을 작성해야합니다. 해당 사이트로 이동하여 IP 주소를 찾아서 반환합니다. HTML 파싱이 필요하지 않습니다!
Robin Day

2
형식을 완전히 제어 할 수있는 임의의 문자열이있는 경우 문자열이 제대로 구성된 XML이라는 사실은 실제로 관련이 없습니다. 그러나 XML의 사용 사례는 실제로이 범주에 속하지 않습니다.
Robert Rossney

15
나는 고통스런 경험을 통해 터무니없이 복잡한 정규식 패턴을 사용하여 원하는 것을 얻을 수 있다고 대부분 말할 수 있습니다. 웹 사이트가 재미없는 작은 변화를 겪을 때까지이 정규식을 던져서 창 밖으로 이틀 동안 울고 새로 시작할 수 있습니다.
Thomasz 2009

@Robert : "거의 사용 사례가 없습니다"는 과장된 것입니다. 내 경험에는 일반적으로 충분한 유스 케이스가 있습니다. YAGNI가 여기에 적용됩니다 ... 때때로. 요령은 해결해야 할 특정 작업에 대해 방탄 및 오래 지속되는 솔루션의 필요성을 아는 것입니다. 로빈은 좋은 지적이 있습니다. 그는 완전한 XML 파싱이 항상 그만한 가치가있는 것은 아니라고 말하고 있습니다. 사용 방법을 알고 있더라도 마찬가지입니다.
LarsH

6

사람들은 일반적으로 욕심 많은 패턴을 쓰는 것을 기본으로 생각하며, 종종 생각할 수없는. * 파일을 대량의 청크를 가능한 가장 큰 <foo>. * </ foo>로 끌어들입니다.


2
와 함께 반복을 게으르게 만드는 것뿐만 아니라 .*?<, 같은 부정 문자 클래스를 사용하여 문제를 해결할 수 [^<]*<있습니다. (면책 조항 : 분명히 그것은 여전히 ​​바보가 아닙니다. 그것은 문제의 핵심입니다.)
Rory O'Kane

6

나는 "바퀴를 다시 발명하지 말라"고 유혹하고 있습니다. XML은 실제로 매우 복잡한 형식입니다. 아마 "싱크로 트로트 론을 재발 명하지 마십시오"라고 말해야 할 것입니다.

아마도 올바른 진부한 시작은 "당신이 가진 모든 것이 망치 일 때 ..."정규 표현식을 사용하는 방법을 알고 있는데, 정규 표현식은 구문 분석에 능숙합니다. 왜 XML 구문 분석 라이브러리를 배우는 것이 귀찮습니까?

XML 구문 분석이 어렵 기 때문 입니다. XML 파싱 라이브러리를 사용하는 법을 배우지 않아도되는 노력은 많은 창의적인 작업과 버그 해결에 따른 것 이상입니다. 귀하를 위해 Google "XML 라이브러리"를 사용하고 다른 사람의 작업을 활용하십시오.


3
C ++만큼 복잡하지는 않습니다.
Cole Johnson

6
@Cole "Cole9"Johnson RE를 사용하여 C ++을 구문 분석하지 않습니다.
아이작 라 비노 비치

2
XML이 싱크로트론 인 경우 C ++는 Large Hadron Collider입니다.
Kevin Kostlan

4

나는 고전 이 당신이 찾고있는 정보를 가지고 있다고 생각 합니다 . 의견 중 하나에서 요점을 찾을 수 있습니다.

여기에 결함이 있다고 생각합니다. HTML은 Chomsky Type 2 문법 (문맥이없는 문법)이고 RegEx는 Chomsky Type 3 문법 (정규 표현식)입니다. 유형 2 문법은 유형 3 문법보다 근본적으로 복잡하기 때문에이 작업을 수행 할 수는 없습니다 . 그러나 많은 사람들이 시도 할 것이고, 어떤 사람들은 성공을 주장 할 것이고, 다른 사람들은 잘못을 찾아 내고 당신을 완전히 엉망으로 만들 것입니다.

Wikipedia의 더 많은 정보 : Chomsky Hierarchy


6
"정규 표현"은 공식 문법 토론에서 여기와 정확히 같은 의미를 갖지 않습니다. 가장 현존하는 정규식 엔진은 Chomsky Type 3 문법보다 강력합니다 (예 : 욕심없는 매칭, 역 참조). Perl과 같은 일부 정규식 엔진은 Turing이 완료되었습니다. 이것들조차 HTML을 파싱하기에 열악한 도구라는 것은 사실이지만, 종종 언급되는 논쟁은 그 이유가 아닙니다.
dubiousjim

4

문제는 다음과 같이 요약됩니다.

  1. 정규식은 거의 부정확합니다. 올바르게 일치하지 않는 합법적 인 입력이 있습니다. 충분히 열심히 일하면 99 % 올바르거나 99.999 % 올릴 수 있지만, 엔티티를 사용하여 XML이 허용하는 이상한 것들 때문에 100 % 올바르 게 만드는 것은 거의 불가능합니다.

  2. 정규식이 정확하지 않은 경우 (0.00001 %의 입력에 대해조차도) 누군가가 애플리케이션을 중단시키는 하나의 입력을 발견 할 수 있기 때문에 보안 문제가 있습니다.

  3. 정규식이 99.99 %의 사례를 포괄 할 수있을만큼 정확하다면이를 완전히 읽을 수없고 유지 보수 할 수 없을 것입니다.

  4. 보통 크기의 입력 파일에서 정규 표현식이 매우 제대로 수행되지 않을 가능성이 큽니다. XML을 처음 접한 것은 들어오는 XML 문서를 올바른 XML 파서로 잘못 분석 한 Perl 스크립트를 대체하는 것이 었으며, 읽을 수없는 코드 300 줄을 누구나 이해할 수있는 100 줄로 바꾸었을뿐만 아니라 사용자 응답 시간을 개선했습니다. 10 초에서 약 0.1 초


1

일반적으로 XML 문법은 결코 정규적이지 않기 때문에 정규식을 사용하여 XML을 구문 분석 할 수 없습니다. 간단히 말해서, 정규 표현식은 셀 수 없습니다 (물론, Perl 정규 표현식은 실제로 계산할 수 있습니다).

동의하지 않습니다. 정규식에서 재귀를 사용하면 열기 및 닫기 태그를 쉽게 찾을 수 있습니다.

여기에 내가 먼저 메시지에서 예 분석 오류를 방지하기 위해 정규 표현식의 예를 보여 주었다.


첫째, 재귀 정규 표현식은 정규 표현식이 아닙니다 (괄호를 보면 재귀 적 인 Perl의 정규 표현식이 HTML을 처리하는 데 필요한 것을 계산할 수 있음을 알 수 있습니다). 둘째, 귀하의 예는 XHTML 또는 XML 형식입니다. HTML이 제대로 구성되지 않았습니다. 셋째, 재귀 정규 표현식 언어 또는 범용 프로그래밍 언어로 작성된 파서를 확장하고 유지 관리하는 것이 더 쉬운 지 스스로에게 묻어 야합니다.
Chas. Owens

넷째, 귀하의 예제조차도 여전히 유효한 XML 인 동안 사소하게 손상되었습니다. content_block과 id 사이에 하나의 공백을 추가하면 실패합니다. 몇 분 더 보냈다면 코드에서 다른 구조적 오류를 발견 할 것입니다. 좋은 생각이 아닙니다.
Chas. Owens

1

나는 여기서이 문제에 대한 간단한 대답을 했다 . 100 %를 차지하지는 않지만, 전처리 작업을 기꺼이 수행 할 수있는 방법에 대해 설명합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.