XML과 특히 HTML 을 구문 분석하는 올바른 도구 는 정규식 엔진이 아니라 파서 라는 데 동의합니다 . 그러나 다른 사람들이 지적했듯이 때로는 정규식을 사용하는 것이 더 빠르고 쉽고 데이터 형식을 알고 있으면 작업을 수행합니다.
Microsoft는 실제로 .NET Framework의 정규 표현식에 대한 모범 사례 섹션을 보유하고 있으며 특히 입력 소스 고려에 대해 설명 합니다 .
정규식에는 제한이 있지만 다음을 고려 했습니까?
.NET 프레임 워크는 Balancing Group Definitions를 지원한다는 점에서 정규식에있어 고유합니다 .
이러한 이유로 정규 표현식을 사용하여 XML을 구문 분석 할 수 있다고 생각합니다. 그러나 유효한 XML이어야합니다 ( 브라우저는 HTML을 매우 용서하고 HTML 내부에서 잘못된 XML 구문을 허용합니다 ). "밸런싱 그룹 정의"를 통해 정규 표현식 엔진이 PDA로 작동 할 수 있기 때문에 가능합니다.
위에서 인용 한 기사 1의 인용문 :
.NET 정규식 엔진
상술 한 바와 같이, 적절히 균형 잡힌 구성은 정규식으로 기술 될 수 없다. 그러나 .NET 정규식 엔진은 균형 잡힌 구문을 인식 할 수있는 몇 가지 구문을 제공합니다.
(?<group>)
-이름 그룹이있는 캡처 스택에서 캡처 된 결과를 푸시합니다.
(?<-group>)
-캡처 그룹에서 이름 그룹과 함께 가장 많이 캡처합니다.
(?(group)yes|no)
-이름 그룹이있는 그룹이 있으면 예 부분과 일치하고 그렇지 않으면 부분과 일치하지 않습니다.
이러한 구성을 통해 .NET 정규식을 통해 간단한 버전의 스택 작업 (푸시, 팝 및 빈)을 기본적으로 허용함으로써 제한된 PDA를 에뮬레이션 할 수 있습니다. 간단한 작업은 각각 증가, 감소 및 0과 비교하는 것과 거의 같습니다. 이를 통해 .NET 정규식 엔진은 컨텍스트가없는 언어의 하위 집합, 특히 간단한 카운터 만 필요한 언어를 인식 할 수 있습니다. 결과적으로 비 전통적인 .NET 정규 표현식이 적절히 균형 잡힌 개별 구성을 인식 할 수 있습니다.
다음 정규식을 고려하십시오.
(?=<ul\s+id="matchMe"\s+type="square"\s*>)
(?>
<!-- .*? --> |
<[^>]*/> |
(?<opentag><(?!/)[^>]*[^/]>) |
(?<-opentag></[^>]*[^/]>) |
[^<>]*
)*
(?(opentag)(?!))
플래그를 사용하십시오.
- 한 줄
- 패턴 공백 무시 (정규 표현식을 축소하고 모든 공백을 제거하는 경우 필요하지 않음)
- 케이스 무시 (필요하지 않음)
정규식 설명 (인라인)
(?=<ul\s+id="matchMe"\s+type="square"\s*>) # match start with <ul id="matchMe"...
(?> # atomic group / don't backtrack (faster)
<!-- .*? --> | # match xml / html comment
<[^>]*/> | # self closing tag
(?<opentag><(?!/)[^>]*[^/]>) | # push opening xml tag
(?<-opentag></[^>]*[^/]>) | # pop closing xml tag
[^<>]* # something between tags
)* # match as many xml tags as possible
(?(opentag)(?!)) # ensure no 'opentag' groups are on stack
A Better .NET Regular Expression Tester 에서 시도해 볼 수 있습니다 .
샘플 소스를 사용했습니다.
<html>
<body>
<div>
<br />
<ul id="matchMe" type="square">
<li>stuff...</li>
<li>more stuff</li>
<li>
<div>
<span>still more</span>
<ul>
<li>Another >ul<, oh my!</li>
<li>...</li>
</ul>
</div>
</li>
</ul>
</div>
</body>
</html>
이것은 일치하는 것을 발견했습니다 :
<ul id="matchMe" type="square">
<li>stuff...</li>
<li>more stuff</li>
<li>
<div>
<span>still more</span>
<ul>
<li>Another >ul<, oh my!</li>
<li>...</li>
</ul>
</div>
</li>
</ul>
실제로 다음과 같이 나왔습니다.
<ul id="matchMe" type="square"> <li>stuff...</li> <li>more stuff</li> <li> <div> <span>still more</span> <ul> <li>Another >ul<, oh my!</li> <li>...</li> </ul> </div> </li> </ul>
마지막으로 Jeff Atwood의 기사 : Parsing Html The Cthulhu Way를 즐겼습니다 . 재밌게도 현재 4k 이상 투표 한이 질문에 대한 답변을 인용합니다.