【问题标题】:Converting HTML to XML将 HTML 转换为 XML
【发布时间】:2012-05-15 11:26:10
【问题描述】:

我有数百个需要用 XML 转换的 HTML 文件。我们使用这些 HTML 为应用程序提供内容,但现在我们必须将这些内容作为 XML 提供。

HTML 文件是 contains、tables、div's、image's、p's、b 或 strong tags 等。

我用谷歌搜索并找到了一些应用程序,但我还无法实现。

您能建议一种将这些文件内容转换为 XML 的方法吗?

【问题讨论】:

  • 看看this post。然后,仔细查看fourth comment。为什么要将 HTML 转换为 XML?
  • @RobW 我会检查它。我们将 HTML 作为内容提供给某些应用程序,但现在我们必须作为 XML 提供。
  • @RobW,我也知道 XML 和 HTML 之间的区别。但我需要解析它的内容并放入 XML。
  • @bahadirarslan:您需要说明您想要这样做的目的。在最坏的情况下,如果您愿意,您可能会拥有一个 HTML 文档的愚蠢 XML 表示,将每个字符放入自己的元素中(这可能不是您想要的,但您会将 HTML 文档转换为 XML)。
  • @bahadir HTML 解析器比 XML 容忍得多。如果幸运的话,将其转换为XHTML 文档,通过在<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 前面加上前缀就足够了(将脚本包装在<script> 块中的//<![CDATA[<newline> ...content... //]]></script> 部分中)。当您的 HTML 不是 well-formed 时,您必须寻找一个 HTML 解析器,它提供了 Export-as-XML 选项。

标签: html xml


【解决方案1】:

我成功使用了tidy 命令行实用程序。在 linux 上,我使用apt-get install tidy 快​​速安装了它。然后是命令:

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

提供了一个 xml 文件,我可以使用 xslt 处理器对其进行处理。但是我需要正确设置 xhtml1 dtds。

这是他们的主页:html-tidy.org(以及旧版:HTML Tidy

【讨论】:

  • 还有xmllint -html -xmlout
  • 我有时也用它。我认为您应该对此做出单独的回答。
  • 它会从 html 文件中删除 javascript
  • 这通常有效,但对于一些 HTML5 文档,我得到空输出。
  • 第一眼看 Tidy 的主页就知道他们自 2008 年以来就没有更新过项目。这可能解释了问题。
【解决方案2】:

我确实找到了一种将(甚至是糟糕的)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;
        } ;
    }

现在这也允许将更多的 html 片段添加到我需要自己使用的一个 XML 中。一般可以这样使用:

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

在此示例中,'&lt;p&gt;test&lt;font&gt;two&lt;/p&gt;' 将很好地以格式良好的 XML 输出为“&lt;info&gt;&lt;p&gt;test&lt;font&gt;two&lt;/font&gt;&lt;/p&gt;&lt;/info&gt;”。添加了 info 根标记,因为它还允许转换不是 XML 的“&lt;p&gt;one&lt;/p&gt;&lt;p&gt;two&lt;/p&gt;”,因为它没有一个根元素。但是,如果您的 html 确实有一个根元素,则可以跳过额外的根 &lt;info&gt; 标记。

有了这个,我可以从非结构化甚至损坏的 HTML 中获得非常好的 XML!

我希望它有点清楚,并且可能有助于其他人使用它。

【讨论】:

    【解决方案3】:

    请记住,HTML 和 XML 在标记语言树中是两个不同的概念。你不能完全是 replace HTML with XML 。 XML 可以被视为 HTML 的一种通用形式,但即使这样也是不精确的。您主要使用 HTML 来显示数据,使用 XML 来承载(或存储)数据。

    此链接很有帮助:How to read HTML as XML?

    More here - difference between HTML and XML

    【讨论】:

    • @boudou。不,XHTML 是 XML,HTML 不是。
    • 那么你的建议是什么?如果我首先将 HTML 转换为 XHTML,那么我可以轻松地转换为 XML 吗?
    • @bahadirarslan 如果您已经设法将您的 HTML 转换为 XHTML,它将是 XML。尽管它们相似,但这并不一定容易。它还取决于您想用这个 XML 做什么。 XML 本身并没有真正的意义。您可以拥有您的自定义模式、RDF+XML、XHTML、SOAP 消息……所有不同类型的 XML。
    猜你喜欢
    • 1970-01-01
    • 2016-12-30
    • 2014-06-20
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    相关资源
    最近更新 更多