Ignore some TR nodes - html-agility-pack

I have a HTML like
<body>
<tr class="sysinfoTableCategoryHeader">
<td colspan="4">Operating System</td>
</tr>
<tr class="sysinfoTablePropertyEven">
<td />
<td />
<td><span class="sysinfoTablePropertyKey">Operating System Name</span></td>
<td><span class="sysinfoTablePropertyValue">Linux</span></td>
</tr>
<tr class="sysinfoTablePropertyOdd">
<td />
<td />
<td><span class="sysinfoTablePropertyKey">Kernel Version</span></td>
<td><span class="sysinfoTablePropertyValue">4.8.0-1-amd64</span></td>
</tr>
<tr class="sysinfoTableCategoryHeader">
<td colspan="4">Motherboard</td>
</tr>
<tr class="sysinfoTablePropertyEven">
<td />
<td />
<td><span class="sysinfoTablePropertyKey">Manufacturer</span></td>
<td><span class="sysinfoTablePropertyValue">Acer</span></td>
</tr>
<tr class="sysinfoTablePropertyOdd">
<td />
<td />
<td><span class="sysinfoTablePropertyKey">Product</span></td>
<td><span class="sysinfoTablePropertyValue">Aspire E5-531</span></td>
</tr>
</body>
So I'm able to pick entire body from this html file which is actually awesome. But there is one problem . Lets say from that body i want to ignore the node with class name="sysinfoTableCategoryHeader" Operating system.
Is this doable at all ?
My output should be like this
<body>
<tr class="sysinfoTableCategoryHeader">
<td colspan="4">Motherboard</td>
</tr>
<tr class="sysinfoTablePropertyEven">
<td />
<td />
<td><span class="sysinfoTablePropertyKey">Manufacturer</span></td>
<td><span class="sysinfoTablePropertyValue">Acer</span></td>
</tr>
<tr class="sysinfoTablePropertyOdd">
<td />
<td />
<td><span class="sysinfoTablePropertyKey">Product</span></td>
<td><span class="sysinfoTablePropertyValue">Aspire E5-531</span></td>
</tr>
</body>
How can i acoomplish it with HTMLAGILITYPACK ??

I'm english a little.
exp code:
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(your html code);
HtmlNodeCollection htmlNodes = htmlDoc.DocumentNode.SelectNodes("//body/tr[#class!='sysinfoTableCategoryHeader']");
the htmlNodes is you needs.
Or use RemoveAllIDforNode();
HtmlNodeCollection htmlNodes = htmlDoc.DocumentNode.SelectNodes("//body/tr[#class='sysinfoTableCategoryHeader']");
foreach (HtmlNode node in htmlNodes) {
htmlDoc.DocumentNode.RemoveAllIDforNode(node);
}

you need find xpath //tr[#class!='sysinfoTableCategoryHeader']
the xpath have operator.

Related

Why Xpath 3.0 works, but Xquery 3.0 doesn't work with the same expression

I launched Xpath in Oxygen. In Xpath 3.0 found what i need but in Xquery 3.0 doesn't find.
This is my Xpath expression
//table[tbody/tr/th/p[contains(text(), 'All Water System Contacts')]]/tbody/tr[3]/td[1]
This is my xml code
I put part code.
<table border="1" cellpadding="1" cellspacing="1" summary="." width="640">
<tbody>
<tr>
<th colspan="3">
<p>All Water System Contacts </p></th>
</tr>
<tr>
<th>Type</th>
<th>Contact</th>
<th>Communication</th>
</tr>
<tr>
<td align="center">AC - Administrative Contact - GENERAL MANAGER </td>
<td align="center">GRANT, JOHN, W <br/> PO BOX 869<br/> BIG SPRING, TX 79721-0869 </td>
<td align="center">
<table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse"
width="100%">
<tbody>
<tr>
<th><b>Electronic Type</b></th>
<th><b>Value</b></th>
</tr>
</tbody>
</table>
<table border="1" cellpadding="0" cellspacing="0" style="border-collapse: collapse"
width="100%">
<tbody>
<tr>
<th><b>Phone Type</b></th>
<th><b>Value</b></th>
</tr>
<tr>
<td align="center">BUS - Business</td>
<td align="center">432-267-6341 </td>
</tr>
<tr>
<td align="center">FAX - Facsimile</td>
<td align="center">432-267-3121 </td>
</tr>
<tr>
<td align="center">BUS - Business</td>
<td align="center">432-267-6070 </td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td align="center">OW - Owner </td>
<td align="center">COLORADO RIVER MUNICIPAL WATER DISTRICT <br/> PO BOX 869<br/> BIG
SPRING, TX 79721-0869 </td>
<td align="center"> </td>
</tr>
</tbody>
</table>
I tried different functions.
I don't know why it doesn't work and what difference
Please help me.
I suspect your real, complete input has an XHTML default namespace declaration xmlns="http://www.w3.org/1999/xhtml" and in oXygen for XPath you have the setting enabled to "use the default namespace of the root element" so your path works with XPath out of the box while for XQuery you need to make sure you explicitly set
declare default element namespace 'http://www.w3.org/1999/xhtml';
in the prolog of your XQuery file or code sample.

Optimal XPath Query for processing the sample HTML fragment

I have a feed that outputs HTML. The following segment is part of the output
<div class="leftnav">
<table border="0" cols="2">
<tr>
<td colspan="2" class="topline"><span style="font-size: 1px"> </span></td>
</tr>
<tr>
<td colspan="2"><span class="bold">Article Cat1 </span></td>
</tr>
<tr>
<td class="date" colspan="2">
ArticleTitle1</td>
</tr>
<tr>
<td width="20"></td>
<td class="date">
ArticleLink1
</td>
</tr>
<tr>
<td colspan="2" class="topline"><span style="font-size: 1px"> </span></td>
</tr>
<tr>
<td colspan="2"><span class="bold">Article Cat2 </span></td>
</tr>
<tr>
<td class="date" colspan="2">
ArticleTitle2</td>
</tr>
<tr>
<td width="20"></td>
<td class="date">
ArticleLink2
</td>
</tr>
</table>
</div>
I want to process above segment using XPATH so that output looks like this
Article Cat1
ArticleTitle1
ArticleLink1 Article Cat2
ArticleTitle2
ArticleLink2
What is the optimal XPATH that will produce the desired output? I tried //div[#class="leftnav"]/table/tr but this gives all the TR elements. I want to skip the first TR element so that I can get the output in the format I described above.
//div[#class="leftnav"]/table/tr[position() > 1]
Try the above
Stupid simple way:
substring-after(normalize-space(string(//*:div)), normalize-space(string(//*:div/*:table/*[1])))
Result: "Article Cat1 ArticleTitle1 ArticleLink1 nbsp Article Cat2 ArticleTitle2 ArticleLink2"
I don't know why, but (position() > 1) doesn't work in my environment, so I've used strings instead.

How to create a two column email newsletter

I am trying to create a two column email flyer but I'm having trouble with the coding as Outlook hates CSS.
I'm using tables to keep it as simple as possible but I want two separate tables on the left and the right so I can add data into it as I wish.
I tried using float left and right on the two tables but Outlook ignores this style.
I know the two grey tables at the bottom are each in their own separate "holder" tables but this is so I can duplicate the grey "data" tables for when I add new articles.
<table class="all" width="auto" height="auto" border="0" cellspacing="0"><tr><td height="504">
<table width="750" height="140" border="0" cellspacing="0">
<tr>
<td width="200" valign="bottom" bgcolor="#E6E6E6"> </td>
<td width="345" align="center" valign="bottom" bgcolor="#E6E6E6"> </td>
<td width="152" align="center" valign="bottom" bgcolor="#E6E6E6"> </td>
<td width="45" align="center" valign="bottom" bgcolor="#E6E6E6"> </td>
</tr>
<tr>
<td width="200" valign="bottom" bgcolor="#E6E6E6"> </td>
<td align="center" valign="bottom" bgcolor="#E6E6E6"><font color="#111111" face="Arial Narrow" size="+2">DECEMBER NEWSLETTER</font></td>
<td width="152" align="center" valign="bottom" bgcolor="#E6E6E6"><font size="2"><strong>#4 - <span class="orange">04.12.13</span></strong></font></td>
<td width="45" align="center" valign="bottom" bgcolor="#E6E6E6"> </td>
</tr>
</table>
<table width="750" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="75" height="50" bgcolor="#E6E6E6" scope="row"> </td>
<td width="600" rowspan="2" scope="row"><img src="http://placehold.it/600x200"/></td>
<td width="75" bgcolor="#E6E6E6" scope="row"> </td>
</tr>
<tr>
<td width="75" height="81" scope="row"> </td>
<td scope="row"> </td>
</tr>
</table>
<table class="holder" width="750" border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top" scope="row">
<table class="inlinetableleft" width="360">
<tr>
<td width="371" align="left">
<!------------LEFT COLUMN------------------>
<table width="360" border="0" cellspacing="0" cellpadding="0">
<tr>
<th height="103" colspan="4" align="left" valign="middle" bgcolor="#CCCCCC" scope="row"> </th>
</tr>
</table>
<!--------------LEFT COLUMN END------------->
</td>
</tr>
</table>
<table class="inlinetableright" width="360">
<tr>
<td align="left">
<!------------RIGHT COLUMN------------------>
<table width="360" border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="106" align="left" bgcolor="#CCCCCC" scope="row"> </td>
</tr>
</table>
<!-----------RIGHT COLUMN END-------------->
</td></tr>
</table>
</td>
</tr>
</table>
Here is a fiddle of my newsletter so far, it's the bottom two grey tables that I want to be side by side.
Fiddle
For HTML emails, nested tables are your friend :)
JSFiddle
Note: the border around the table is just to show you where the tables are.
<table border="0" width="600" cellpadding="0" cellspacing="0" align="center">
<tr>
<td colspan="2">
header content here
</td>
</tr>
<tr>
<td width="300">
<table border="0" width="300" cellpadding="1" cellspacing="0" align="left">
<tr>
<td>Left Content</td>
</tr>
</table>
</td>
<td width="300">
<table border="0" width="300" cellpadding="1" cellspacing="0" align="left">
<tr>
<td>Right content</td>
</tr>
</table>
</td>
</tr>
</table>

prototype : update tbody content dynamically

I have below HTML, i am trying to update the content of tbody dynamically using ajax. I have response html all i want is to update the tbody content using prototype. Till now i have tried $('table-body').innerHTML="html content here";
<tbody class="table-body">
<tr>
<td id="11" class="consumables model" width="15%">Aficion SP 20022</td>
<td id="12" class="consumables type" width="15%">Print Cartridge</td>
<td class="consumables" width="15%">Black </td>
<td class="consumables" width="15%">15000 </td>
<td class="consumables" width="15%">
<td class="consumables" width="25%">
</tr>
<tr>
<td id="10" class="consumables model" width="15%">Aficion SP 2002</td>
<td id="12" class="consumables type" width="15%">Print Cartridge</td>
<td class="consumables" width="15%">Black </td>
<td class="consumables" width="15%">15000 </td>
<td class="consumables" width="15%">
<td class="consumables" width="25%">
</tr>
<tr>
<td id="2" class="consumables model" width="15%">Aficion SP C242SF</td>
<td id="14" class="consumables type" width="15%">Print cartridge SP 4100</td>
<td class="consumables" width="15%">Magenta </td>
<td class="consumables" width="15%">50000 </td>
<td class="consumables" width="15%">
<td class="consumables" width="25%">
</tr>
</tbody>
There are 2 ways to solve this
change the class to an id on the <tbody> tag and then do $('table-body').update("html content here")
use the class to select the first element matching that selector $$('.table-body').first().update("html content here")

Escaping characters with ajax and ColdFusion

Hello I've got an issue with an encode failing. Can anyone spot where I'm going wrong?
<form>
<table cellspacing="0" cellpadding="0" border="0" style="background-color:#ededed;padding:50px;">
<tr>
<td align="left"><b>Screen? (eg. Index)</b></td>
</tr>
<tr>
<td align="left"><input type="text" name="strFeedbackScreen" value="" style="width:300px;"></td>
</tr>
<tr>
<td style="height:10px"></td>
</tr>
<tr>
<td align="left"><b>Comments:</b></td>
</tr>
<tr>
<td align="left"><textarea name="strFeedbackComments" style="width:400px;height:150px;"></textarea></td>
</tr>
<tr>
<td style="height:10px"></td>
</tr>
<tr>
<td align="left"><b>Thank you for your feedback.</b></td>
</tr>
<tr>
<td style="height:10px"></td>
</tr>
<cfoutput>
<tr>
<td align="left"><input type="button" value="Send" class="button"
onMouseover="this.className = 'buttonover';"
onMousedown="this.className = 'buttonover';"
onMouseOut="this.className = 'button';"
onclick="sendfeedback('strFeedbackScreen='+escape(this.form.strFeedbackScreen.value)+',strFeedbackComments='+escape(this.form.strFeedbackComments.value),'send_feedback_action_ajax')">
</td>
</tr>
</cfoutput>
</table>
</form>
is the form
<cfoutput>
<cfmail to="feedback#example.com" from="feedback#example.com" subject="Feedback left" type="html">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>**** This email has been sent to all concerned ****</td>
</tr>
<tr>
<td style="height:10px;"> </td>
</tr>
<cfif application.ds eq "App1">
<tr>
<td>This feedback has been left on App 1.</td>
</tr>
<cfelseif application.ds eq "App2">
<tr>
<td>This feedback has been left on App 2.</td>
</tr>
<cfelseif application.ds eq "App3">
<tr>
<td>This feedback has been left on App 3.</td>
</tr>
</cfif>
<tr>
<td style="height:10px;"> </td>
</tr>
<tr>
<td><b>From:</b></td>
</tr>
<tr>
<td>#session.stafffirstname# #session.staffsurname# - #session.staffemail#</td>
</tr>
<tr>
<td style="height:10px;"> </td>
</tr>
<tr>
<td><b>Screen:</b></td>
</tr>
<tr>
<td>#strFeedbackScreen#</td>
</tr>
<tr>
<td style="height:10px;"> </td>
</tr>
<tr>
<td><b>Comments:</b></td>
</tr>
<tr>
<td>#strFeedbackComments#</td>
</tr>
</table>
</cfmail>
</cfoutput>
is the action.cfm
and the javascript is
function sendfeedback(fields,action) {
turnLayeron('ajaxloading');
nocache = Math.random();
http.open('get', '/ajax.cfm?action='+action+'&fields='+fields+'&nocache='+nocache);
http.onreadystatechange = function() {
if(http.readyState == 4){
closepopout();
turnLayeroff('ajaxloading');
}
};
http.send(null);
}
I've been trying to get uriencode working, but it encodes my string before it gets emailed.
Change your JavaScript to following:
function sendfeedback(fields,action) {
http.open("POST", '/ajax.cfm?action='+action+'&nocache='+nocache, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == 4){
closepopout();
turnLayeroff('ajaxloading');
}
};
http.send(fields);
}
Also change your function call to:
onclick="sendfeedback('strFeedbackScreen='+escape(this.form.strFeedbackScreen.value)+'&strFeedbackComments='+escape(this.form.strFeedbackComments.value),'send_feedback_action_ajax')"

Resources