2014-07-17 41 views
5

Tôi đang cố gắng phân tích cú pháp một số HTML đã được rút gọn thành xml hợp lệ, sử dụng this function.Tại sao tôi không thể phân tích cú pháp HTML đã được cắt thành XML?

mã kiểm tra của tôi (với chức năng htmlParse sao chép và dán từ blog Ben Nadel của):

<cfscript> 
    // I take an HTML string and parse it into an XML(XHTML) 
    // document. This is returned as a standard ColdFusion XML 
    // document. 
    function htmlParse(htmlContent, disableNamespaces = true){ 

     // Create an instance of the Xalan SAX2DOM class as the 
     // recipient of the TagSoup SAX (Simple API for XML) compliant 
     // events. TagSoup will parse the HTML and announce events as 
     // it encounters various HTML nodes. The SAX2DOM instance will 
     // listen for such events and construct a DOM tree in response. 
     var saxDomBuilder = createObject("java", "com.sun.org.apache.xalan.internal.xsltc.trax.SAX2DOM").init(); 

     // Create our TagSoup parser. 
     var tagSoupParser = createObject("java", "org.ccil.cowan.tagsoup.Parser").init(); 

     // Check to see if namespaces are going to be disabled in the 
     // parser. If so, then they will not be added to elements. 
     if (disableNamespaces){ 

     // Turn off namespaces - they are lame an nobody likes 
     // to perform xmlSearch() methods with them in place. 
     tagSoupParser.setFeature(
     tagSoupParser.namespacesFeature, 
     javaCast("boolean", false) 
     ); 

     } 

     // Set our DOM builder to be the listener for SAX-based 
     // parsing events on our HTML. 
     tagSoupParser.setContentHandler(saxDomBuilder); 

     // Create our content input. The InputSource encapsulates the 
     // means by which the content is read. 
     var inputSource = createObject("java", "org.xml.sax.InputSource").init(
     createObject("java", "java.io.StringReader").init(htmlContent) 
     ); 

     // Parse the HTML. This will trigger events which the SAX2DOM 
     // builder will translate into a DOM tree. 
     tagSoupParser.parse(inputSource); 

     // Now that the HTML has been parsed, we have to get a 
     // representation that is similar to the XML document that 
     // ColdFusion users are used to having. Let's search for the 
     // ROOT document and return is. 
     return(
     xmlSearch(saxDomBuilder.getDom(), "/node()")[ 1 ] 
     ); 

    } 
</cfscript> 
<cfset html='<tr > <td align="center"> <span id="id1" >Compliance Review</span> </td><td class="center"> <span id="id2" >395.8(i)</span> </td><td align="left"> <span id="id3" >Failing to submit a record of duty status within 13 days </span> </td><td class="center" > <span id="id4">4/17/2014</span> </td> </tr>' /> 
<cfset parsedData = htmlParse(html) /> 

(Các html nhận được ở định dạng này từ một chức năng khác nhau, nhưng tôi đã cố gắng thể xác định rõ chuỗi cho bây giờ để theo dõi các vấn đề)

tôi nhận được lỗi sau:.

NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist. 
The error occurred in myfilePath/myfileName.cfm: line 42 

40 :  // Parse the HTML. This will trigger events which the SAX2DOM 
41 :  // builder will translate into a DOM tree. 
42 :  tagSoupParser.parse(inputSource); 

gì đang xảy ra vậy? Làm thế nào tôi có thể sửa nó?

+0

Trong khi bạn đang sử dụng ColdFusion để gọi các phương thức, bạn có sử dụng thẳng lên Java ở đây. Nó chỉ trông giống như đầu vào không được định dạng tốt hoặc có lỗi trong trình phân tích cú pháp. –

+0

@ J.T. - không phải là điểm mà nó cũng làm việc cho "bẩn" html và đầu vào không phải được định dạng tốt? – froadie

+1

@froadie Không chắc chắn về các vấn đề của Tagsoup, nhưng tôi đã sử dụng Jsoup và nó hoạt động tốt. Hai liên kết này có thể hữu ích. http://www.raymondcamden.com/2012/4/6/jsoup-adds-jQuerylike-parsing-in-Java và http://www.bennadel.com/blog/2358-parsing-traversing-and-mutating- html-with-coldfusion-and-jsoup.htm –

Trả lời

2

Tôi chưa sử dụng TagSoup nhưng tôi đã sử dụng jTidy trong nhiều năm với kết quả tuyệt vời để lấy HTML do người dùng cung cấp từ tất cả các loại nguồn (kể cả MS Word) và làm sạch nó sao cho nó trả về XHTML.

Bạn có thể thử jTidy trên cùng một tài liệu bằng cách thả jar jTidy lên đường dẫn lớp hoặc sử dụng JavaLoader để tải nó. Vì bạn đang sử dụng CF10, bạn có thể sử dụng this method to include the JAR.

Sau đó, dưới đây là cách để gọi jTidy trong cfscript:

jTidy = createObject("java", "org.w3c.tidy.Tidy"); 

jTidy.setQuiet(false); 
jTidy.setIndentContent(true); 
jTidy.setSmartIndent(true); 
jTidy.setIndentAttributes(true); 
jTidy.setWraplen(1024); 
jTidy.setXHTML(true); 
jTidy.setNumEntities(true); 
jTidy.setConvertWindowsChars(true);    
jTidy.setFixBackslash(true);  // changes \ in urls to/
jTidy.setLogicalEmphasis(true);  // uses strong/em instead of b/i 
jTidy.setDropEmptyParas(true); 

// create the in and out streams for jTidy 
readBuffer = CreateObject("java","java.lang.String").init(parseData).getBytes(); 
inP = createobject("java","java.io.ByteArrayInputStream").init(readBuffer); 
outx = createObject("java", "java.io.ByteArrayOutputStream").init(); 

// do the parsing 
jTidy.parse(inP,outx); 
outstr = outx.toString(); 

này sẽ trở lại XHTML hợp lệ mà bạn có thể truy vấn đối với XPath. Tôi quấn ở trên vào một chức năng makeValid() và sau đó chạy nó chống lại HTML của bạn:

<cfset html='<tr > <td align="center"> <span id="id1" >Compliance Review</span> </td><td class="center"> <span id="id2" >395.8(i)</span> </td><td align="left"> <span id="id3" >Failing to submit a record of duty status within 13 days </span> </td><td class="center" > <span id="id4">4/17/2014</span> </td> </tr>' /> 
<cfset out = makeValid(html) /> 
<cfdump var="#xmlParse(out)#" /> 

Và đây là kết quả:

Picture of the cfdump output from xmlParse()

+0

Tôi thực sự đã kết thúc bằng cách sử dụng Jsoup theo nhận xét của @ GauravS ... Nhưng cảm ơn vì điều này, và liên kết về cách bao gồm các lọ cũng hữu ích. – froadie

Các vấn đề liên quan