C #으로 XML에서 중복 특성을 제거하는 방법

c# html-agility-pack validation xml

문제

제 3 자 공급자로부터 일부 XML 파일을 파싱하고 불행히도 때로는 일부 요소에 중복 특성이 포함되어 있기 때문에 항상 올바른 형식의 XML이 아닙니다.

원본을 제어 할 수 없으며 어떤 요소에 중복 특성이 있는지 알지 못하거나 중복 된 특성 이름을 미리 알고 있습니다.

분명히 XMLDocument 객체에 내용을로드하면 중복 속성에 XmlException이 발생하기 때문에 XmlReader 를 사용하여 XML 요소를 단계별로 처리하고 문제가되는 요소에 도달하면 중복 속성을 처리 할 수 ​​있습니다.

그러나 요소의 특성을 insepct 할 기회가 오기 전에 reader.Read() 에서 XmlException 이 발생합니다.

다음은이 문제를 보여주는 샘플 방법입니다.

public static void ParseTest()
{
    const string xmlString = 
        @"<?xml version='1.0'?>
        <!-- This is a sample XML document -->
        <Items dupattr=""10"" id=""20"" dupattr=""33"">
            <Item>test with a child element <more/> stuff</Item>
        </Items>";

    var output = new StringBuilder();
    using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
    {
        XmlWriterSettings ws = new XmlWriterSettings();
        ws.Indent = true;
        using (XmlWriter writer = XmlWriter.Create(output, ws))
        {
            while (reader.Read())   /* Exception throw here when Items element encountered */
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        writer.WriteStartElement(reader.Name);
                        if (reader.HasAttributes){ /* CopyNonDuplicateAttributes(); */}
                        break;
                    case XmlNodeType.Text:
                        writer.WriteString(reader.Value);
                        break;
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.ProcessingInstruction:
                        writer.WriteProcessingInstruction(reader.Name, reader.Value);
                        break;
                    case XmlNodeType.Comment:
                        writer.WriteComment(reader.Value);
                        break;
                    case XmlNodeType.EndElement:
                        writer.WriteFullEndElement();
                        break;
                }
            }

        }
    }
    string str = output.ToString();
}

입력을 파싱하고 정규 표현식과 문자열 조작을 사용하지 않고 중복 속성을 제거하는 다른 방법이 있습니까?

수락 된 답변

XML을 HTML 문서로 생각하여 해결책을 찾았습니다. 그런 다음 오픈 소스 Html Agility Pack 라이브러리를 사용하여 유효한 XML을 얻을 수있었습니다.

트릭은 먼저 HTML 헤더로 XML을 저장하는 것이 었습니다.
그래서 XML 선언을 대체하십시오.
<?xml version="1.0" encoding="utf-8" ?>
HTML 선언은 다음과 같습니다.
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

내용이 파일에 저장되면이 메서드는 유효한 XML 문서를 반환합니다.

// Requires reference to HtmlAgilityPack
public XmlDocument LoadHtmlAsXml(string url)
{
    var web = new HtmlWeb();

    var m = new MemoryStream();
    var xtw = new XmlTextWriter(m, null);

    // Load the content into the writer
    web.LoadHtmlAsXml(url, xtw);

    // Rewind the memory stream
    m.Position = 0;

    // Create, fill, and return the xml document
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml((new StreamReader(m)).ReadToEnd());
    return xmlDoc;
}

중복 된 속성 노드는 이전 속성 값을 덮어 쓰는 최신 속성 값 으로 자동 제거됩니다 .


인기 답변

좋습니다, 오류를 잡을 필요가 있다고 생각합니다.

그럼 당신은 다음과 같은 방법을 사용할 수 있어야합니다 :

reader.MoveToFirstAttribute();

reader.MoveToFirstAttribute();

다음 속성을 얻으려면 :

reader.MoveToFirstAttribute();

이렇게하면 모든 속성 값을 가져올 수 있습니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.