it-swarm.com.de

Wie konvertiere ich HTML in PHP mit PHP?

Ich kann JSON mit JsontoHtml library in HTML konvertieren. Jetzt muss ich HTML in JSON konvertieren, wie auf dieser Site gezeigt. Beim Durchschauen des Codes habe ich folgendes Skript gefunden:

<script>
$(function(){

    //HTML to JSON
    $('#btn-render-json').click(function() {

        //Set html output
        $('#html-output').html( $('#html-input').val() );

        //Process to JSON and format it for consumption
        $('#html-json').html( FormatJSON(toTransform($('#html-output').children())) );
    });

});

//Convert obj or array to transform
function toTransform(obj) {

    var json;

    if( obj.length > 1 )
    {
        json = [];

        for(var i = 0; i < obj.length; i++)
            json[json.length++] = ObjToTransform(obj[i]);
    } else
        json = ObjToTransform(obj);

    return(json);
}

//Convert obj to transform
function ObjToTransform(obj)
{
    //Get the DOM element
    var el = $(obj).get(0);

    //Add the tag element
    var json = {'tag':el.nodeName.toLowerCase()};

    for (var attr, i=0, attrs=el.attributes, l=attrs.length; i<l; i++){
        attr = attrs[i];
        json[attr.nodeName] = attr.value;
    }

    var children = $(obj).children();

    if( children.length > 0 ) json['children'] = [];
    else json['html'] = $(obj).text();

    //Add the children
    for(var c = 0; c < children.length; c++)
        json['children'][json['children'].length++] = toTransform(children[c]);

    return(json);
}

//Format JSON (with indents)
function FormatJSON(oData, sIndent) {
    if (arguments.length < 2) {
        var sIndent = "";
    }
    var sIndentStyle = "  ";
    var sDataType = RealTypeOf(oData);

    // open object
    if (sDataType == "array") {
        if (oData.length == 0) {
            return "[]";
        }
        var sHTML = "[";
    } else {
        var iCount = 0;
        $.each(oData, function() {
            iCount++;
            return;
        });
        if (iCount == 0) { // object is empty
            return "{}";
        }
        var sHTML = "{";
    }

    // loop through items
    var iCount = 0;
    $.each(oData, function(sKey, vValue) {
        if (iCount > 0) {
            sHTML += ",";
        }
        if (sDataType == "array") {
            sHTML += ("\n" + sIndent + sIndentStyle);
        } else {
            sHTML += ("\"" + sKey + "\"" + ":");
        }

        // display relevant data type
        switch (RealTypeOf(vValue)) {
            case "array":
            case "object":
                sHTML += FormatJSON(vValue, (sIndent + sIndentStyle));
                break;
            case "boolean":
            case "number":
                sHTML += vValue.toString();
                break;
            case "null":
                sHTML += "null";
                break;
            case "string":
                sHTML += ("\"" + vValue + "\"");
                break;
            default:
                sHTML += ("TYPEOF: " + typeof(vValue));
        }

        // loop
        iCount++;
    });

    // close object
    if (sDataType == "array") {
        sHTML += ("\n" + sIndent + "]");
    } else {
        sHTML += ("}");
    }

    // return
    return sHTML;
}

//Get the type of the obj (can replace by jquery type)
function RealTypeOf(v) {
  if (typeof(v) == "object") {
    if (v === null) return "null";
    if (v.constructor == (new Array).constructor) return "array";
    if (v.constructor == (new Date).constructor) return "date";
    if (v.constructor == (new RegExp).constructor) return "regex";
    return "object";
  }
  return typeof(v);
}
</script>

enter image description here

Nun brauche ich die folgende Funktion in PHP. Ich kann die HTML-Daten erhalten. Jetzt brauche ich nur noch die JavaScript-Funktion in die Funktion PHP zu konvertieren. Ist das möglich? Meine größten Zweifel sind folgende:

  • Die primäre Eingabe für die Javascript-Funktion toTransform() ist ein Objekt. Ist es möglich, HTML über PHP in Objekte zu konvertieren?

  • Sind alle Funktionen in diesem bestimmten JavaScript in PHP verfügbar? 

Bitte schlagen Sie mir die Idee vor.

Wenn ich versuchte, das Skript-Tag gemäß der angegebenen Antwort in Json zu konvertieren, erhalte ich Fehler. Als ich es in der json2html-Site ausprobierte, zeigte es sich so:enter image description here .. Wie erreicht man die gleiche Lösung?

16
Ganesh Babu

Wenn Sie ein DOMDocument-Objekt erhalten können, das Ihr HTML darstellt, müssen Sie es nur rekursiv durchlaufen und die gewünschte Datenstruktur erstellen.

Das Konvertieren Ihres HTML-Dokuments in eine DOMDocument sollte so einfach sein:

function html_to_obj($html) {
    $dom = new DOMDocument();
    $dom->loadHTML($html);
    return element_to_obj($dom->documentElement);
}

Dann könnte eine einfache Durchquerung von $dom->documentElement, die die von Ihnen beschriebene Struktur angibt, folgendermaßen aussehen:

function element_to_obj($element) {
    $obj = array( "tag" => $element->tagName );
    foreach ($element->attributes as $attribute) {
        $obj[$attribute->name] = $attribute->value;
    }
    foreach ($element->childNodes as $subElement) {
        if ($subElement->nodeType == XML_TEXT_NODE) {
            $obj["html"] = $subElement->wholeText;
        }
        else {
            $obj["children"][] = element_to_obj($subElement);
        }
    }
    return $obj;
}

Testfall

$html = <<<EOF
<!DOCTYPE html>
<html lang="en">
    <head>
        <title> This is a test </title>
    </head>
    <body>
        <h1> Is this working? </h1>  
        <ul>
            <li> Yes </li>
            <li> No </li>
        </ul>
    </body>
</html>

EOF;

header("Content-Type: text/plain");
echo json_encode(html_to_obj($html), JSON_PRETTY_PRINT);

Ausgabe

{
    "tag": "html",
    "lang": "en",
    "children": [
        {
            "tag": "head",
            "children": [
                {
                    "tag": "title",
                    "html": " This is a test "
                }
            ]
        },
        {
            "tag": "body",
            "html": "  \n        ",
            "children": [
                {
                    "tag": "h1",
                    "html": " Is this working? "
                },
                {
                    "tag": "ul",
                    "children": [
                        {
                            "tag": "li",
                            "html": " Yes "
                        },
                        {
                            "tag": "li",
                            "html": " No "
                        }
                    ],
                    "html": "\n        "
                }
            ]
        }
    ]
}

Antwort auf die aktualisierte Frage

Die oben vorgeschlagene Lösung funktioniert nicht mit dem <script>-Element, da sie nicht als DOMText, sondern als DOMCharacterData-Objekt analysiert wird. Dies liegt daran, dass die DOM-Erweiterung in PHP auf libxml2, basiert, das Ihren HTML-Code als HTML 4.0 analysiert. In HTML 4.0 hat der Inhalt von <script> den Typ CDATA und nicht #PCDATA.

Sie haben zwei Lösungen für dieses Problem.

  1. Die einfache, aber nicht sehr robuste Lösung wäre das Hinzufügen des LIBXML_NOCDATA-Flags zu DOMDocument::loadHTML. (Ich bin nicht wirklich zu 100% sicher, ob dies für den HTML-Parser funktioniert.)

  2. Die schwierigere, aber meiner Meinung nach bessere Lösung, ist das Hinzufügen eines zusätzlichen Tests, wenn Sie $subElement->nodeType vor der Rekursion testen. Die rekursive Funktion würde zu:

function element_to_obj($element) {
    echo $element->tagName, "\n";
    $obj = array( "tag" => $element->tagName );
    foreach ($element->attributes as $attribute) {
        $obj[$attribute->name] = $attribute->value;
    }
    foreach ($element->childNodes as $subElement) {
        if ($subElement->nodeType == XML_TEXT_NODE) {
            $obj["html"] = $subElement->wholeText;
        }
        elseif ($subElement->nodeType == XML_CDATA_SECTION_NODE) {
            $obj["html"] = $subElement->data;
        }
        else {
            $obj["children"][] = element_to_obj($subElement);
        }
    }
    return $obj;
}

Wenn Sie auf einen anderen Fehler dieses Typs stoßen, sollten Sie zuerst den Typ des Knotens $subElement überprüfen, da viele andere Möglichkeiten vorhanden ist, mit dem sich meine kurze Beispielfunktion nicht befasste.

Außerdem werden Sie feststellen, dass libxml2 Fehler in Ihrem HTML-Code beheben muss, um ein DOM dafür erstellen zu können. Deshalb werden ein <html>- und ein <head>-Element angezeigt, auch wenn Sie sie nicht angeben. Sie können dies vermeiden, indem Sie das Flag LIBXML_HTML_NOIMPLIED verwenden.

Testfall mit Skript

$html = <<<EOF
        <script type="text/javascript">
            alert('hi');
        </script>
EOF;

header("Content-Type: text/plain");
echo json_encode(html_to_obj($html), JSON_PRETTY_PRINT);

Ausgabe

{
    "tag": "html",
    "children": [
        {
            "tag": "head",
            "children": [
                {
                    "tag": "script",
                    "type": "text\/javascript",
                    "html": "\n            alert('hi');\n        "
                }
            ]
        }
    ]
}
22
scozy

Ich gehe davon aus, dass Ihre HTML-Zeichenfolge in der Variable $html gespeichert ist. Also solltest du tun:

$dom = new DOMDocument();
$dom->loadHTML($html);

foreach($dom->getElementsByTagName('*') as $el){
    $result[] = ["type" => $el->tagName, "value" => $el->nodeValue];
}

$json = json_encode($result, JSON_UNESCAPED_UNICODE);

Hinweis : Dieser Algorithmus unterstützt keine Parent-Child-Tags und ruft alle Tags als übergeordnete Elemente ab und analysiert sie alle in einer sortierten Warteschlange. Natürlich können Sie diese Funktion implementieren, indem Sie die DOMDocument-Klassenfunktionen untersuchen.

1
Amir Forsati