我有数百个需要在 XML 中转换的 HTML 文件。我们使用这些 HTML 为应用程序提供内容,但现在我们必须将这些内容作为 XML 提供。
HTML 文件有 contains、tables、div's、image's、p's、b 或 strong 标签等。
我用谷歌搜索并找到了一些应用程序,但我还无法实现。
您能建议一种将这些文件内容转换为 XML 的方法吗?
我成功使用了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)
我确实找到了一种将(甚至是糟糕的)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>';
在此示例'<p>test<font>two</p>'
中,将很好地以格式良好的 XML 输出为 ' <info><p>test<font>two</font></p></info>
'。添加了 info 根标记,因为它还允许转换<p>one</p><p>two</p>
不是 XML 的 ' ',因为它没有一个根元素。但是,如果您的 html 确实有一个根元素,则<info>
可以跳过额外的根标签。
有了这个,我从非结构化甚至损坏的 HTML 中得到了真正好的 XML!
我希望它有点清楚,并且可能有助于其他人使用它。
请记住,HTML 和 XML 是标记语言树中的两个不同概念。您不能将 HTML 完全替换为 XML 。XML 可以被视为 HTML 的一种通用形式,但即使这样也是不精确的。您主要使用 HTML 来显示数据,使用 XML 来承载(或存储)数据。
此链接很有帮助:如何将 HTML 读取为 XML?