Piszę rozszerzenie Chrome, aby konwertować strony HTML w inny format.

Jeśli używam document.getElementsByTagName("*") i iterować tę kolekcję, widzę wszystkie tagi. Jednak jest to płaska reprezentacja. Muszę wykryć otwarcie i zamykanie "wydarzenia", podobnie jak parser SAX, dzięki czemu moje przetłumaczone wyjście utrzymuje odpowiednie ograniczenie / zagnieżdżanie.

Jaki jest właściwy sposób na to w JavaScript? Wydaje się trochę niezręcznie musi zrobić ręcznie. Czy jest jakiś inny sposób, aby to zrobić?

Aby zilustrować, co mam na myśli ...

   <html>
       <body>
           <h1>Header</h1>
           <div>
               <p>some text and a missing closing tag
               <p>some more text</p>
           </div>
           <p>some more dirty HTML
        </body>
    <html>

Muszę uzyskać wydarzenia w tej kolejności:

    html open
    body open
    h1 open
    text
    h1 close
    div open
    p open
    text
    p close
    p open
    text
    p close
    div close
    p open
    text
    p close
    body close
    html close

Dostaję uczucie, które zależy ode mnie, aby śledzić wydarzenia podobne do parsera Saxa jako część mojej iteracji. Czy są dla mnie jakieś inne opcje? Jeśli nie, możesz wskazać mnie do dowolnego przykładowego kodu?

Dzięki!

0
Lee Grey 18 sierpień 2012, 05:02

2 odpowiedzi

Najlepsza odpowiedź

Po prostu przemierzaj każdy węzeł i wszystkie dzieci każdego węzła. Gdy poziom dzieci jest wyczerpany, znacznik jest zamknięty.

function parseChildren(node) {

    // if this a text node, it has no children or open/close tags
    if(node.nodeType == 3) {
        console.log("text");
        return;
    }

    console.log(node.tagName.toLowerCase() + " open");

    // parse the child nodes of this node
    for(var i = 0; i < node.childNodes.length; ++i) {
        parseChildren(node.childNodes[i]);
    }

    // all the children are used up, so this tag is done
    console.log(node.tagName.toLowerCase() + " close");
}

Przemierzać całą stronę, po prostu zrobić parseChildren(document.documentFragment). Możesz zastąpić instrukcje console.log z dowolnym zachowaniem.

Należy pamiętać, że ten kod zgłasza wiele węzłów text, ponieważ białe znaki między znacznikami liczy się jako węzeł tekstowy. Aby tego uniknąć, po prostu rozszerzaj kod obsługi tekstu:

    if(node.nodeType == 3) {
        // if this node is all whitespace, don't report it
        if(node.data.replace(/\s/g,'') == '') { return; }

        // otherwise, report it
        console.log("text");
        return;
    }
2
apsillers 18 sierpień 2012, 01:41

Nie sądzę, że istnieje narzędzie, więc powinieneś pisać trochę funkcji rekurencyjnej, w której będziesz get first child, get next node, get parent w jakiś sposób i tak dalej.

0
Danil Speransky 18 sierpień 2012, 01:08