형제 속성을 기반으로 노드 선택 - HtmlAgilityPack - C #

c# html-agility-pack html-parsing

문제

나는 다음과 같이 구성된 HTML 문서를 가지고있다.

<ul class="beverageFacts">
<li>
    <span>Vintage</span> 
    <strong>2007&nbsp;</strong>
</li>
<li>
    <span>ABV</span> 
    <strong>13,0&nbsp;%</strong>
</li>
<li>
    <span>Sugar</span> 
    <strong>5&nbsp;gram/liter</strong>
</li>

<span> 태그의 값에 따라 해당 string 에 대한 <strong> 태그의 값을 구문 분석해야합니다.

나는 다음과 같은 것을 가지고있다.

String vintage;
String sugar;
String abv;

현재 beverageFacts -node의 각 자식 노드를 루핑하여 값을 검사하여 올바른 해당 string 로 구문 분석 string . 지금까지 "Vintage"값을 얻으려는 코드는 다음과 같지만 결과는 항상 null 입니다.

HtmlNodeCollection childNodes = bevFactNode.ChildNodes;
foreach (HtmlNode subNode in childNodes)
{
    if (subNode.InnerText.TrimStart() == "Vintage")
        vintage = subNode.NextSibling.InnerText.Trim();
}

내 노드 선택이 잘못되었다고 생각하지만 가장 효율적인 방법으로 제대로 수행하는 방법을 알 수는 없습니다.

이것을 달성하기위한 쉬운 방법이 있습니까?


2013 년 7 월 29 일 수정

다음 코드를 사용하여 주석에서 enricoariel 이 제안한 공백을 제거하려고했습니다.

        HtmlAgilityPack.HtmlDocument page = new HtmlWeb().Load("http://www.systembolaget.se/" + articleID);

        string cleanDoc = Regex.Replace(page.DocumentNode.OuterHtml, @"\s*(?<capture><(?<markUp>\w+)>.*<\/\k<markUp>>)\s*", "${capture}", RegexOptions.Singleline);

        HtmlDocument cleanPage = new HtmlDocument();
        cleanPage.LoadHtml(cleanDoc);

결과는 여전히

 String vintage = null;

수락 된 답변

HTML 마크 업을 보면 노드에서 충분히 깊숙이 가지 않았다는 것을 알았습니다. enricoariel이 지적했듯이, 내가 제대로 청소하지 못하는 공백이 있습니다. 공백 인 형제를 건너 뛰고 대신 다음 위치로 이동하여 올바른 결과를 얻습니다.

        foreach (HtmlNode bevFactNode in bevFactsNodes)
        {
            HtmlNodeCollection childNodes = bevFactNode.ChildNodes;
            foreach (HtmlNode node in childNodes)
            {
                foreach(HtmlNode subNode in node.ChildNodes)
                {
                    if (subNode.InnerText.Trim() == "Årgång")
                        vintage = HttpUtility.HtmlDecode(subNode.NextSibling.NextSibling.InnerText.Trim());
                }
            }
        }
        Console.WriteLine("Vintage: " + vintage);

출력 할 것이다.

Vintage: 2007

HTML을 디코딩하여 결과의 ​​형식을 올바르게 지정합니다.

교훈!


인기 답변

요약하면 가장 좋은 해결책은 nextSibling 값을 검색하기 전에 정규 표현식을 사용하여 모든 공백을 제거하는 것입니다.

    string myHtml =
    @"
    <ul class='beverageFacts'>
    <li>
        <span>Vintage</span> 
        <strong>2007&nbsp;</strong>
    </li>
    <li>
        <span>ABV</span> 
        <strong>13,0&nbsp;%</strong>
    </li>
    <li>
        <span>Sugar</span> 
        <strong>5&nbsp;gram/liter</strong>
    </li>";
    //Remove space after and before tag
myHtml = Regex.Replace(myHtml, @"\s+<", "<", RegexOptions.Multiline | RegexOptions.Compiled);
myHtml = Regex.Replace(myHtml, @">\s+", "> ", RegexOptions.Compiled | RegexOptions.Multiline);

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(myHtml.Replace("/r", "").Replace("/n", "").Replace("/r/n", "").Replace("  ", ""));
doc.OptionFixNestedTags = true;

HtmlNodeCollection vals = doc.DocumentNode.SelectNodes("//ul[@class='beverageFacts']//span");

var myNodeContent = string.Empty;
foreach (HtmlNode val in vals)
{
    if (val.InnerText == "Vintage")
    {
        myNodeContent = val.NextSibling.InnerText;
    }
}

return myNodeContent;



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