tôi đã tìm ra một cách để chuyển đổi (thậm chí xấu) html vào XML cũng được hình thành. Tôi bắt đầu dựa trên hàm DOM loadHTML này. Tuy nhiên trong thời gian một số vấn đề xảy ra và tôi tối ưu hóa và thêm các bản vá lỗi để sửa các tác dụng phụ.
function tryToXml($dom,$content) {
if(!$content) return false;
// xml well formed content can be loaded as xml node tree
$fragment = $dom->createDocumentFragment();
// wonderfull appendXML to add an XML string directly into the node tree!
// aappendxml will fail on a xml declaration so manually skip this when occurred
if(substr($content,0, 5) == '<?xml') {
$content = substr($content,strpos($content,'>')+1);
if(strpos($content,'<')) {
$content = substr($content,strpos($content,'<'));
}
}
// if appendXML is not working then use below htmlToXml() for nasty html correction
if([email protected]$fragment->appendXML($content)) {
return $this->htmlToXml($dom,$content);
}
return $fragment;
}
// convert content into xml
// dom is only needed to prepare the xml which will be returned
function htmlToXml($dom, $content, $needEncoding=false, $bodyOnly=true) {
// no xml when html is empty
if(!$content) return false;
// real content and possibly it needs encoding
if($needEncoding) {
// no need to convert character encoding as loadHTML will respect the content-type (only)
$content = '<meta http-equiv="Content-Type" content="text/html;charset='.$this->encoding.'">' . $content;
}
// return a dom from the content
$domInject = new DOMDocument("1.0", "UTF-8");
$domInject->preserveWhiteSpace = false;
$domInject->formatOutput = true;
// html type
try {
@$domInject->loadHTML($content);
} catch(Exception $e){
// do nothing and continue as it's normal that warnings will occur on nasty HTML content
}
// to check encoding: echo $dom->encoding
$this->reworkDom($domInject);
if($bodyOnly) {
$fragment = $dom->createDocumentFragment();
// retrieve nodes within /html/body
foreach($domInject->documentElement->childNodes as $elementLevel1) {
if($elementLevel1->nodeName == 'body' and $elementLevel1->nodeType == XML_ELEMENT_NODE) {
foreach($elementLevel1->childNodes as $elementInject) {
$fragment->insertBefore($dom->importNode($elementInject, true));
}
}
}
} else {
$fragment = $dom->importNode($domInject->documentElement, true);
}
return $fragment;
}
protected function reworkDom($node, $level = 0) {
// start with the first child node to iterate
$nodeChild = $node->firstChild;
while ($nodeChild) {
$nodeNextChild = $nodeChild->nextSibling;
switch ($nodeChild->nodeType) {
case XML_ELEMENT_NODE:
// iterate through children element nodes
$this->reworkDom($nodeChild, $level + 1);
break;
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
// do nothing with text, cdata
break;
case XML_COMMENT_NODE:
// ensure comments to remove - sign also follows the w3c guideline
$nodeChild->nodeValue = str_replace("-","_",$nodeChild->nodeValue);
break;
case XML_DOCUMENT_TYPE_NODE: // 10: needs to be removed
case XML_PI_NODE: // 7: remove PI
$node->removeChild($nodeChild);
$nodeChild = null; // make null to test later
break;
case XML_DOCUMENT_NODE:
// should not appear as it's always the root, just to be complete
// however generate exception!
case XML_HTML_DOCUMENT_NODE:
// should not appear as it's always the root, just to be complete
// however generate exception!
default:
throw new exception("Engine: reworkDom type not declared [".$nodeChild->nodeType. "]");
}
$nodeChild = $nodeNextChild;
} ;
}
Bây giờ điều này cũng cho phép thêm nhiều phần html vào một XML mà tôi cần sử dụng. Nói chung nó có thể được sử dụng như thế này:
$c='<p>test<font>two</p>';
$dom=new DOMDocument('1.0', 'UTF-8');
$n=$dom->appendChild($dom->createElement('info')); // make a root element
if($valueXml=tryToXml($dom,$c)) {
$n->appendChild($valueXml);
}
echo '<pre/>'. htmlentities($dom->saveXml($n)). '</pre>';
Trong ví dụ này '<p>test<font>two</p>'
độc đáo sẽ được outputed trong XML cũng được hình thành như '<info><p>test<font>two</font></p></info>
'. Thẻ gốc của thông tin được thêm vào vì nó cũng sẽ cho phép chuyển đổi '<p>one</p><p>two</p>
' không phải là XML vì nó không có một phần tử gốc. Tuy nhiên, nếu html của bạn chắc chắn có một phần tử gốc thì có thể bỏ qua thêm thẻ gốc <info>
.
Với điều này, tôi nhận được XML thực sự tốt đẹp từ HTML không có cấu trúc và thậm chí bị hỏng!
Tôi hy vọng nó hơi rõ ràng và có thể đóng góp cho người khác sử dụng nó.
Hãy xem [bài đăng này] (http://stackoverflow.com/a/85922/938089). Sau đó, có một cái nhìn rất gần [bình luận thứ tư] (http://stackoverflow.com/questions/84556/#comment1436887_85922). Tại sao bạn muốn chuyển đổi HTML sang XML? –
@RobW tôi sẽ kiểm tra. Chúng tôi đã phân phối HTML dưới dạng nội dung cho một số ứng dụng nhưng giờ đây chúng tôi phải phân phát dưới dạng XML. –
@RobW, tôi cũng biết sự khác biệt giữa XML và HTML. Nhưng tôi cần phải phân tích nội dung của nó và đưa vào XML. –