Avatar
matesax
Redaktor
Avatar
matesax:

Dobrý den,
již jsem prakticky dodělal HTML parser. Jenže nemohl jsem jej udělat plně objektově, neboť si nedokáži poradit s nekonečným vnořováním tagů. Totiž objektově jsem to navrhl takto:

public interface ITag
{
        string Name { get; set; }

        Dictionary<string, string> Parameters { get; set; }

        int Start { get; set; }

        int End { get; set; }
}

public class Tag : ITag
{
        public string Name { get; set; }

        public Dictionary<string, string> Parameters { get; set; }

        public List<ITag> Childrens { get; set; }

        /// <summary>
        /// Start position in parent tag string.
        /// </summary>
        public int Start { get; set; }

        /// <summary>
        /// End position in parent tag string.
        /// </summary>
        public int End { get; set; }

        public Tag()
        {
                Name = "";
                Parameters = new Dictionary<string, string>();
                Childrens = new List<ITag>();
        }

        /// <summary>
        /// Get parameters from one-pair tag or opening tag of two-pair tag.
        /// </summary>
        public static Dictionary<string, string> ParseParameters(string tag)
        {
                Dictionary<string, string> parameters = new Dictionary<string, string>();

                foreach (Match m in Regex.Matches(tag, @"\S+\s*=\s*" + '"' + "[^" + '"' + "]*"))
                        try
                        {
                                string[] parameter = Regex.Split(m.Value, @"s*=\s*" + '"');

                                parameters.Add(parameter[0], parameter[1]);
                        }
                        catch {}

                return parameters;
        }

        /// <summary>
        /// Get name from one-pair tag or opening tag of two-pair tag.
        /// </summary>
        /// <exception cref="System.Exception">Throw when fail to get a name of tag.</exception>
        public static string ParseName(string tag)
        {
                try
                {
                        return Regex.Match(tag, "").Value;
                }
                catch (System.Exception e)
                {
                        throw e;
                }
        }

        /// <summary>
        /// Parse one-pair tag or opening tag of two-pair tag.
        /// </summary>
        public static Tag Parse(string tag)
        {
                return new Tag()
                {
                        Name = Tag.ParseName(tag),
                        Parameters = Tag.ParseParameters(tag)
                };
        }
}

Ale jak budu dostávat texty z jednotlivých tagů? Napadlo mne zaznamenávat někde mapu zanoření, ale to také nebude ono...

public List<ITag> Childrens { get; set; }// dítě v dítěti v dítěti...

Aktuálně tedy při získávání tagů okamžitě dostávám i text - problém je, že to odporuje OOP návrhu structu Page. Hlavně tím celkem ztrácí smysl třída Tag - přitom ale tento objektový přístup potřebuji... Děkuji za užitečné nápady. :)

Editováno 20.1.2013 9:22
 
Odpovědět 20.1.2013 9:21
Avatar
lcet.m
Člen
Avatar
lcet.m:

Co takhle v teto fázi pouzit HTML agility pack? Můžeš si všechno parsovani schovat za nějaký interface a az budeš mít hotovy browser, můžeš si implementovat vlastni parser. Myslím ale, ze cesta nevede pres regexy - ty jsou na takové použití příliš pomalé. A co ten prázdný catch - bojis se duplicitnich atributu?

 
Nahoru Odpovědět 20.1.2013 12:24
Avatar
matesax
Redaktor
Avatar
Odpovídá na lcet.m
matesax:

No - jak jinak to parsovat? Vše kolem zpracování HTML je již dokončeno - zápolím již jen s indexem konce dvoupárového tagu. Texty již ale bez problému dostanu objektově do structu Page, bohužel jak jsem psal - tak nějak nevím, zda udržovat i nadále třídu Tag... Každopádně to hlavně jede - a to zatraceně rychle - mým hlavním cílem je ale ta rychlost - takže mi napiš, jak jinak to zpracovat - jen doufám, že dosavadní práci nebudu muset zahodit... :)

Dělám konzolový prohlížeč - vize:

Základním výstupem bude jen text - bez odkazů a formulářů. A k těmto 2 elementům se bude přistupovat odděleně - pomocí příkazů - či přes příslušné panely. Takže všude kde bude odkaz, jej nahradí ID pro příkaz - takže pak třeba zadá uživatel: go 27, nt 27 (new tab)...

Každopádně vše bude maximálně nastavitelné - včetně základního layoutu... Hodlám přejímat i některé styly + trochu z JS - abych nepřišel o nic důležitého...

Editováno 20.1.2013 12:55
 
Nahoru Odpovědět 20.1.2013 12:54
Avatar
matesax
Redaktor
Avatar
matesax:

Problém jsem vyřešil vypsáním stromu do roviny, místo nesmyslného kopírování stromu do jiného stromu. Aby ale vše nebylo po kupě - a byl v tom trochu řád atd., vytvořil jsem blokové propojení - různými odkazy atd. Funguje mi to skoro jako kolekce - jen nemusím pokaždé projíždět obrovský seznam... Nikde jsem ale nějaké pěkné řešení neviděl - a to ani kolem reflexe - vážně není "oficiální" řešení?

Editováno 1.2.2013 19:36
 
Nahoru Odpovědět 1.2.2013 19:34
Avatar
Ben Žour (Jeremy):

Tak se zkus podívat na kód třeba vykreslovacího jádra Gecko co používá Firefox, https://developer.mozilla.org/…ozilla/Gecko?… , já se v tom teda moc nehrabal, C++ ještě zrovna moc neumím ale po chvilce by se tam asi něco dalo najít :)

 
Nahoru Odpovědět 1.2.2013 21:01
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.