2008-11-14 2 views
12

응용 프로그램에서 상당히 큰 XML 출력이 있습니다. 내 프로그램으로 처리 한 다음 원래 프로그램으로 다시 피드해야합니다. 이 XML에는 대체해야 할 부분이 있습니다. 흥미로운 부분은 다음과 같습니다.정규 표현식을 여러 줄로 올바르게 사용할 수 없습니다.

<sys:customtag sys:sid="1" sys:type="Processtart" /> 
    <sys:tag>value</sys:tag> 
    here are some other tags 
    <sys:tag>value</sys.tag> 
<sys:customtag sys:sid="1" sys:type="Procesend" /> 

이 문서에는 이와 같은 여러 부분이 있습니다.

이 태그 안에있는 모든 XML 조각을 수정해야 수정할 수 있습니다. 나는 그 조각을 얻을 수있는 정규 표현식을 썼습니다하지만 그것은 작동하지 않습니다

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.Load(@"output.xml"); 
Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>", RegexOptions.Multiline & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant); 
MatchCollection matches = regExp.Matches(xmlDoc.InnerXml); 

내가 한 줄에 모든 물건을두고 여러 줄 옵션을 사용하지 않고이 정규 표현식을 호출하는 경우, 그것은 모든 발행 수를 찾을 수 없습니다. 파일을 그대로두고 여러 줄 옵션을 설정하면 작동하지 않습니다. 무엇이 문제인가, 무엇을 바꿔야 하는가? 아니면 regexp없이 이러한 태그 사이에 XML 부분을 가져 오는 더 쉬운 방법이 있습니까?

답변

41

나는 사용하는 옵션이 RegexOptions.Multiline (src) 대신 RegexOptions.Singleline이라고 생각합니다. 귀하의 경우 개조가 일치해야합니다 (.).

... 점이 개행과 일치하는 모드를 "단일 행 모드"라고합니다. 이 용어를 "멀티 라인 모드"와 쉽게 섞을 수 있기 때문에 약간 불행합니다. 멀티 라인 모드는 앵커에만 영향을 미치며 싱글 라인 모드는 닷에 영향을 미칩니다. .NET 프레임 워크의 regex 클래스를 사용할 때는 Regex.Match ("string"과 같이 RegexOptions.Singleline을 지정하여이 모드를 활성화하십시오. ","regex ", RegexOptions.Singleline).

+0

: (멀리 여러 RegexOptions 플래그를 사용하는 등)

Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>", RegexOptions.Multiline & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant); 

이 코드가 정확한지 :

이 코드는 잘못 생성자에 두 번째 매개 변수로 제로를 전달합니다 고맙습니다. 멀티 라인 = 멀티 라인 모드도 의미합니다. – Biri

4

RegExp는 xml에 대한 도구가 아닙니다. XDocument/XmlDocument에로드하고 xpath를 사용할 수 있습니까? 수정하려는 내용을 명확히하면 빈 칸을 채울 수 있습니다. 네임 스페이스는 아마도이 경우 복잡하게 만드는 주요 항목 일 수 있으므로 XmlNamespaceManager을 사용해야합니다.

string xml = @"<foo xmlns:sys=""foobar""><bar/><bar><sys:customtag sys:sid=""1"" sys:type=""Processtart"" /> 
<sys:tag>value</sys:tag> 
here are some other tags 
<sys:tag>value</sys:tag> 
<sys:customtag sys:sid=""1"" sys:type=""Procesend"" /></bar><bar/></foo>"; 

    XmlDocument doc = new XmlDocument(); 
    doc.LoadXml(xml); 
    XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable()); 
    mgr.AddNamespace("sys", "foobar"); 
    var matches = doc.SelectNodes("//sys:customtag[@sys:type='Processtart']", mgr); 
    foreach (XmlElement start in matches) 
    { 
     XmlElement end = (XmlElement) start.SelectSingleNode("following-sibling::sys:customtag[@sys:type='Procesend'][1]",mgr); 
     XmlNode node = start.NextSibling; 
     while (node != null && node != end) 
     { 
      Console.WriteLine(node.OuterXml); 

      node = node.NextSibling; 
     } 
    } 
+0

XPath 옵션을 살펴 봤지만 XML과 관련이없는 태그 사이의 XML 내용을 다시 찾을 수있는 항목을 찾지 못했습니다 (즉, 해당 항목이 시작 지점에서 서로 시작 태그가 아님을 의미합니다 XML의). 어쩌면 당신은 생각을 가지고 있을까요? – Biri

+0

음, xml은 트리로 사용하기위한 것입니다 ... 간단한 옵션은 ...을 사용하는 것입니다. .. –

+0

네, 그 문제를 해결할 수는 있지만 불행히도 XML은 변경할 수없는 응용 프로그램에서 나옵니다.이 응용 프로그램에서이 형식으로 다시 제공해야합니다. 내부의 XML 태그를 변경할 수 없습니다. – Biri

4

정규식 문자 : 나는 XML의 뉘앙스에 더 많은 대처하기 위해 기대, 그러나 - 여기

는, 부여, 단지 정규식보다 더 복잡한 예입니다 "." MultiLine 옵션이 설정되어 있어도 개행과 일치하지 않습니다. 대신 [\s\S] 또는 기타 일치 항목을 사용해야합니다.

MultiLine 옵션은의 동작을 수정^(대신 FO 시작 - 중 - 문자열 - 라인 시작)와 $ (끝 (end-of-line) 대신 끝 문자열)

BTW : 실제로 정규식은 HTML을 스캔하는 올바른 방법이 아닙니다 ...

4

여전히 문제가있는 경우 OR 대신 RegexOptions와 AND를 사용하고 있기 때문일 수 있습니다.그것을이다

Regex regExp = new Regex(@"<sys:customtag(.*?)Processtart(.*?)/>(.*?)<sys:customtag (.*?)Procesend(.*?)/>", 
RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.CultureInvariant); 
관련 문제