web-dev-qa-db-ja.com

HTMLからXMLへの変換

XMLに変換する必要があるHTMLファイルがたくさんあります。これらのHTMLを使用してアプリケーションのコンテンツを提供していますが、今ではこれらのコンテンツをXMLとして提供する必要があります。

HTMLファイルには、テーブル、div、画像、p、bまたは強力なタグなどが含まれます。

グーグルで検索していくつかのアプリケーションを見つけましたが、まだ達成できませんでした。

これらのファイルの内容をXMLに変換する方法を提案できますか?

14
bahadir arslan

tidyコマンドラインユーティリティを使用して成功しました。 Linuxでは、apt-get install tidy。次に、コマンド:

tidy -q -asxml --numeric-entities yes source.html >file.xml

xsltプロセッサで処理できるxmlファイルを提供しました。ただし、xhtml1 dtdsを正しく設定する必要がありました。

これは彼らのホームページです: html-tidy.org (そしてレガシーのもの: HTML Tidy

16
Jarekczek

私は(悪い場合でも)htmlを整形式のXMLに変換する方法を見つけました。これをDOMのloadHTML関数に基づいて開始しました。しかし、その間にいくつかの問題が発生し、副作用を修正するためにパッチを最適化および追加しました。

  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(!@$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;
        } ;
    }

これにより、自分で使用する必要がある1つのXMLにさらに多くのhtmlピースを追加することもできます。一般的に、次のように使用できます。

        $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>';

この例では'<p>test<font>two</p>'は、整形式のXMLで '<info><p>test<font>two</font></p></info> '。情報ルートタグは、 '<p>one</p><p>two</p> 'ルート要素が1つもないため、XMLではありません。ただし、htmlに必ず1つのルート要素がある場合は、余分なルート<info>タグはスキップできます。

これにより、構造化されていない、または破損したHTMLからでも実際のNice XMLを取得できます!

私はそれが少し明確であり、それを使用するために他の人々に貢献するかもしれないことを願っています。

2
Bob Siefkes

HTMLとXMLは、マークアップ言語のツリーの2つの異なる概念であることを忘れないでください。 HTMLをXMLに置き換える を正確に指定することはできません。 XMLはHTMLの一般化された形式として見ることができますが、それでも不正確です。主にHTMLを使用してデータを表示し、XMLを使用してデータを保持(または格納)します。

このリンクは役に立ちます: HTMLをXMLとして読む方法

詳細はこちら-HTMLとXMLの違い

1
Coffee