/branches/Customize Specification/Ivony.Html/Extensions/DomExtensions.cs

# · C# · 891 lines · 412 code · 260 blank · 219 comment · 144 complexity · 79419141b5eafd3cc8a476460cc04b90 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace Ivony.Html
  5. {
  6. /// <summary>
  7. /// 提供修改文档对象模型(DOM)的扩展方法
  8. /// </summary>
  9. public static class DomExtensions
  10. {
  11. /// <summary>
  12. /// 创建文档碎片
  13. /// </summary>
  14. /// <param name="document">要创建文档碎片的文档</param>
  15. /// <returns>创建的文档碎片</returns>
  16. public static IHtmlFragment CreateFragment( this IHtmlDocument document )
  17. {
  18. if ( document == null )
  19. throw new ArgumentNullException( "document" );
  20. var manager = document.FragmentManager;
  21. if ( manager == null )
  22. throw new NotSupportedException();
  23. return manager.CreateFragment();
  24. }
  25. /// <summary>
  26. /// 解析 HTML 并创建文档碎片
  27. /// </summary>
  28. /// <param name="document">要创建文档碎片的文档</param>
  29. /// <param name="html">要解析的 HTML</param>
  30. /// <returns>创建的文档碎片</returns>
  31. public static IHtmlFragment ParseFragment( this IHtmlDocument document, string html )
  32. {
  33. if ( document == null )
  34. throw new ArgumentNullException( "document" );
  35. if ( html == null )
  36. throw new ArgumentNullException( "html" );
  37. var manager = document.FragmentManager;
  38. if ( manager == null )
  39. throw new NotSupportedException();
  40. return manager.ParseFragment( html );
  41. }
  42. private static IHtmlDomModifier EnsureModifiable( IHtmlDomObject domObject )
  43. {
  44. if ( domObject == null )
  45. throw new ArgumentNullException( "domObject" );
  46. var modifier = domObject.Document.DomModifier;
  47. if ( modifier == null )
  48. throw new NotSupportedException( "文档不支持修改 DOM 结构" );
  49. return modifier;
  50. }
  51. /// <summary>
  52. /// 尝试为容器添加一个元素
  53. /// </summary>
  54. /// <param name="container">要添加元素的容器</param>
  55. /// <param name="elementName">元素名</param>
  56. /// <returns>创建并添加好的元素</returns>
  57. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  58. public static IHtmlElement AddElement( this IHtmlContainer container, string elementName )
  59. {
  60. if ( container == null )
  61. throw new ArgumentNullException( "container" );
  62. if ( elementName == null )
  63. throw new ArgumentNullException( "elementName" );
  64. lock ( container.SyncRoot )
  65. {
  66. return AddElement( container, container.Nodes().Count(), elementName );
  67. }
  68. }
  69. /// <summary>
  70. /// 尝试为容器添加一个元素
  71. /// </summary>
  72. /// <param name="container">要添加元素的容器</param>
  73. /// <param name="index">添加的位置</param>
  74. /// <param name="elementName">元素名</param>
  75. /// <returns>创建并添加好的元素</returns>
  76. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  77. public static IHtmlElement AddElement( this IHtmlContainer container, int index, string elementName )
  78. {
  79. if ( container == null )
  80. throw new ArgumentNullException( "container" );
  81. if ( elementName == null )
  82. throw new ArgumentNullException( "elementName" );
  83. var modifier = EnsureModifiable( container );
  84. return modifier.AddElement( container, index, elementName );
  85. }
  86. /// <summary>
  87. /// 尝试为容器添加一个文本节点
  88. /// </summary>
  89. /// <param name="container">要添加元素的容器</param>
  90. /// <param name="htmlText">HTML 文本</param>
  91. /// <returns>创建并添加好的文本节点</returns>
  92. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  93. public static IHtmlTextNode AddTextNode( this IHtmlContainer container, string htmlText )
  94. {
  95. if ( container == null )
  96. throw new ArgumentNullException( "container" );
  97. if ( htmlText == null )
  98. throw new ArgumentNullException( "htmlText" );
  99. lock ( container.SyncRoot )
  100. {
  101. return AddTextNode( container, container.Nodes().Count(), htmlText );
  102. }
  103. }
  104. /// <summary>
  105. /// 尝试为容器添加一个文本节点
  106. /// </summary>
  107. /// <param name="container">要添加元素的容器</param>
  108. /// <param name="index">添加的位置</param>
  109. /// <param name="htmlText">HTML 文本</param>
  110. /// <returns>创建并添加好的文本节点</returns>
  111. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  112. public static IHtmlTextNode AddTextNode( this IHtmlContainer container, int index, string htmlText )
  113. {
  114. if ( container == null )
  115. throw new ArgumentNullException( "container" );
  116. if ( htmlText == null )
  117. throw new ArgumentNullException( "htmlText" );
  118. var modifier = EnsureModifiable( container );
  119. return modifier.AddTextNode( container, index, htmlText );
  120. }
  121. /// <summary>
  122. /// 尝试为容器添加一个注释节点
  123. /// </summary>
  124. /// <param name="container">要添加元素的容器</param>
  125. /// <param name="comment">HTML 注释文本</param>
  126. /// <returns>创建并添加好的注释节点</returns>
  127. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  128. public static IHtmlComment AddComment( this IHtmlContainer container, string comment )
  129. {
  130. if ( container == null )
  131. throw new ArgumentNullException( "container" );
  132. if ( comment == null )
  133. throw new ArgumentNullException( "comment" );
  134. lock ( container.SyncRoot )
  135. {
  136. return AddComment( container, container.Nodes().Count(), comment );
  137. }
  138. }
  139. /// <summary>
  140. /// 尝试为容器添加一个注释节点
  141. /// </summary>
  142. /// <param name="container">要添加元素的容器</param>
  143. /// <param name="index">添加的位置</param>
  144. /// <param name="comment">HTML 注释文本</param>
  145. /// <returns>创建并添加好的注释节点</returns>
  146. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  147. public static IHtmlComment AddComment( this IHtmlContainer container, int index, string comment )
  148. {
  149. if ( container == null )
  150. throw new ArgumentNullException( "container" );
  151. if ( comment == null )
  152. throw new ArgumentNullException( "comment" );
  153. var modifier = EnsureModifiable( container );
  154. return modifier.AddComment( container, index, comment );
  155. }
  156. /// <summary>
  157. /// 尝试为容器添加一个文档碎片
  158. /// </summary>
  159. /// <param name="container">要添加碎片的容器</param>
  160. /// <param name="fragment">要添加的碎片</param>
  161. /// <returns></returns>
  162. public static IEnumerable<IHtmlNode> AddFragment( this IHtmlContainer container, IHtmlFragment fragment )
  163. {
  164. if ( container == null )
  165. throw new ArgumentNullException( "container" );
  166. if ( fragment == null )
  167. throw new ArgumentNullException( "fragment" );
  168. lock ( container.SyncRoot )
  169. {
  170. return AddFragment( container, container.Nodes().Count(), fragment );
  171. }
  172. }
  173. /// <summary>
  174. /// 尝试为容器添加一个文档碎片
  175. /// </summary>
  176. /// <param name="container">要添加碎片的容器</param>
  177. /// <param name="index">要添加的位置</param>
  178. /// <param name="fragment">要添加的碎片</param>
  179. /// <returns></returns>
  180. public static IEnumerable<IHtmlNode> AddFragment( this IHtmlContainer container, int index, IHtmlFragment fragment )
  181. {
  182. if ( container == null )
  183. throw new ArgumentNullException( "container" );
  184. if ( fragment == null )
  185. throw new ArgumentNullException( "fragment" );
  186. return fragment.Into( container, index );
  187. }
  188. /// <summary>
  189. /// 尝试为容器添加一个文档碎片
  190. /// </summary>
  191. /// <param name="container">要添加碎片的容器</param>
  192. /// <param name="html">要分析成碎片的 HTML 文本</param>
  193. /// <returns></returns>
  194. public static IEnumerable<IHtmlNode> AddFragment( this IHtmlContainer container, string html )
  195. {
  196. if ( container == null )
  197. throw new ArgumentNullException( "container" );
  198. if ( html == null )
  199. throw new ArgumentNullException( "html" );
  200. var fragment = container.Document.ParseFragment( html );
  201. return AddFragment( container, fragment );
  202. }
  203. /// <summary>
  204. /// 尝试为容器添加一个文档碎片
  205. /// </summary>
  206. /// <param name="container">要添加碎片的容器</param>
  207. /// <param name="index">要添加的位置</param>
  208. /// <param name="html">要分析成碎片的 HTML 文本</param>
  209. /// <returns></returns>
  210. public static IEnumerable<IHtmlNode> AddFragment( this IHtmlContainer container, int index, string html )
  211. {
  212. if ( container == null )
  213. throw new ArgumentNullException( "container" );
  214. if ( html == null )
  215. throw new ArgumentNullException( "html" );
  216. var fragment = container.Document.ParseFragment( html );
  217. return AddFragment( container, index, fragment );
  218. }
  219. /// <summary>
  220. /// 添加节点的副本
  221. /// </summary>
  222. /// <param name="container">要添加副本的容器</param>
  223. /// <param name="textNode">要创作副本的节点</param>
  224. /// <returns>添加后的节点</returns>
  225. public static IHtmlTextNode AddCopy( this IHtmlContainer container, IHtmlTextNode textNode )
  226. {
  227. if ( container == null )
  228. throw new ArgumentNullException( "container" );
  229. if ( textNode == null )
  230. throw new ArgumentNullException( "textNode" );
  231. lock ( container.SyncRoot )
  232. {
  233. return AddCopy( container, container.Nodes().Count(), textNode );
  234. }
  235. }
  236. /// <summary>
  237. /// 添加节点的副本
  238. /// </summary>
  239. /// <param name="container">要添加副本的容器</param>
  240. /// <param name="index">添加的位置</param>
  241. /// <param name="textNode">要创作副本的节点</param>
  242. /// <returns>添加后的节点</returns>
  243. public static IHtmlTextNode AddCopy( this IHtmlContainer container, int index, IHtmlTextNode textNode )
  244. {
  245. if ( container == null )
  246. throw new ArgumentNullException( "container" );
  247. if ( textNode == null )
  248. throw new ArgumentNullException( "textNode" );
  249. return container.AddTextNode( index, textNode.HtmlText );
  250. }
  251. /// <summary>
  252. /// 添加节点的副本
  253. /// </summary>
  254. /// <param name="container">要添加副本的容器</param>
  255. /// <param name="comment">要创作副本的节点</param>
  256. /// <returns>添加后的节点</returns>
  257. public static IHtmlComment AddCopy( this IHtmlContainer container, IHtmlComment comment )
  258. {
  259. if ( container == null )
  260. throw new ArgumentNullException( "container" );
  261. if ( comment == null )
  262. throw new ArgumentNullException( "comment" );
  263. lock ( container.SyncRoot )
  264. {
  265. return AddCopy( container, container.Nodes().Count(), comment );
  266. }
  267. }
  268. /// <summary>
  269. /// 添加节点的副本
  270. /// </summary>
  271. /// <param name="container">要添加副本的容器</param>
  272. /// <param name="index">要添加的位置</param>
  273. /// <param name="comment">要创作副本的节点</param>
  274. /// <returns>添加后的节点</returns>
  275. public static IHtmlComment AddCopy( this IHtmlContainer container, int index, IHtmlComment comment )
  276. {
  277. if ( container == null )
  278. throw new ArgumentNullException( "container" );
  279. if ( comment == null )
  280. throw new ArgumentNullException( "comment" );
  281. return container.AddComment( index, comment.Comment );
  282. }
  283. /// <summary>
  284. /// 添加节点的副本
  285. /// </summary>
  286. /// <param name="container">要添加副本的容器</param>
  287. /// <param name="element">要创作副本的节点</param>
  288. /// <returns>添加后的节点</returns>
  289. public static IHtmlElement AddCopy( this IHtmlContainer container, IHtmlElement element )
  290. {
  291. if ( container == null )
  292. throw new ArgumentNullException( "container" );
  293. if ( element == null )
  294. throw new ArgumentNullException( "element" );
  295. lock ( container.SyncRoot )
  296. {
  297. return AddCopy( container, container.Nodes().Count(), element );
  298. }
  299. }
  300. /// <summary>
  301. /// 添加节点的副本
  302. /// </summary>
  303. /// <param name="container">要添加副本的容器</param>
  304. /// <param name="index">要添加的位置</param>
  305. /// <param name="element">要创作副本的节点</param>
  306. /// <returns>添加后的节点</returns>
  307. public static IHtmlElement AddCopy( this IHtmlContainer container, int index, IHtmlElement element )
  308. {
  309. if ( container == null )
  310. throw new ArgumentNullException( "container" );
  311. if ( element == null )
  312. throw new ArgumentNullException( "element" );
  313. var _element = container.AddElement( index, element.Name );
  314. foreach ( var attribute in element.Attributes() )
  315. _element.AddAttribute( attribute.Name, attribute.AttributeValue );
  316. foreach ( var node in element.Nodes() )
  317. AddCopy( _element, node );
  318. return _element;
  319. }
  320. /// <summary>
  321. /// 添加节点的副本
  322. /// </summary>
  323. /// <param name="container">要添加副本的容器</param>
  324. /// <param name="node">要创作副本的节点</param>
  325. /// <returns>添加后的节点</returns>
  326. public static IHtmlNode AddCopy( this IHtmlContainer container, IHtmlNode node )
  327. {
  328. if ( container == null )
  329. throw new ArgumentNullException( "container" );
  330. if ( node == null )
  331. throw new ArgumentNullException( "node" );
  332. lock ( container.SyncRoot )
  333. {
  334. return AddCopy( container, container.Nodes().Count(), node );
  335. }
  336. }
  337. /// <summary>
  338. /// 添加节点的副本
  339. /// </summary>
  340. /// <param name="container">要添加副本的容器</param>
  341. /// <param name="index">要添加的位置</param>
  342. /// <param name="node">要创作副本的节点</param>
  343. /// <returns>添加后的节点</returns>
  344. public static IHtmlNode AddCopy( this IHtmlContainer container, int index, IHtmlNode node )
  345. {
  346. if ( container == null )
  347. throw new ArgumentNullException( "container" );
  348. if ( node == null )
  349. throw new ArgumentNullException( "node" );
  350. var textNode = node as IHtmlTextNode;
  351. if ( textNode != null )
  352. return AddCopy( container, index, textNode );
  353. var comment = node as IHtmlComment;
  354. if ( comment != null )
  355. return AddCopy( container, index, comment );
  356. var element = node as IHtmlElement;
  357. if ( element != null )
  358. return AddCopy( container, index, element );
  359. throw new NotSupportedException();
  360. }
  361. /// <summary>
  362. /// 添加节点集合的副本
  363. /// </summary>
  364. /// <param name="container">要添加副本的容器</param>
  365. /// <param name="node">要创作副本的节点集合</param>
  366. /// <returns>添加后的节点集合</returns>
  367. public static IEnumerable<IHtmlNode> AddCopy( this IHtmlContainer container, IEnumerable<IHtmlNode> node )
  368. {
  369. if ( container == null )
  370. throw new ArgumentNullException( "container" );
  371. if ( node == null )
  372. throw new ArgumentNullException( "node" );
  373. lock ( container.SyncRoot )
  374. {
  375. return AddCopy( container, container.Nodes().Count(), node );
  376. }
  377. }
  378. /// <summary>
  379. /// 添加节点集合的副本
  380. /// </summary>
  381. /// <param name="container">要添加副本的容器</param>
  382. /// <param name="index">要添加的位置</param>
  383. /// <param name="nodes">要创作副本的节点集合</param>
  384. /// <returns>添加后的节点集合</returns>
  385. public static IEnumerable<IHtmlNode> AddCopy( this IHtmlContainer container, int index, IEnumerable<IHtmlNode> nodes )
  386. {
  387. if ( container == null )
  388. throw new ArgumentNullException( "container" );
  389. if ( nodes == null )
  390. throw new ArgumentNullException( "nodes" );
  391. List<IHtmlNode> result = new List<IHtmlNode>( nodes.Count() );
  392. lock ( container.SyncRoot )
  393. {
  394. foreach ( var node in nodes.Reverse() )
  395. {
  396. var textNode = node as IHtmlTextNode;
  397. if ( textNode != null )
  398. {
  399. result.Add( AddCopy( container, index, textNode ) );
  400. continue;
  401. }
  402. var comment = node as IHtmlComment;
  403. if ( comment != null )
  404. {
  405. result.Add( AddCopy( container, index, comment ) );
  406. continue;
  407. }
  408. var element = node as IHtmlElement;
  409. if ( element != null )
  410. {
  411. result.Add( AddCopy( container, index, element ) );
  412. continue;
  413. }
  414. throw new NotSupportedException();
  415. }
  416. return result.ToArray();
  417. }
  418. }
  419. /// <summary>
  420. /// 创建碎片的副本
  421. /// </summary>
  422. /// <param name="fragment">要创建副本的碎片</param>
  423. /// <returns>碎片的副本</returns>
  424. public static IHtmlFragment MakeCopy( this IHtmlFragment fragment )
  425. {
  426. if ( fragment == null )
  427. throw new ArgumentNullException( "fragment" );
  428. var _fragment = fragment.Document.CreateFragment();
  429. foreach ( var node in fragment.Nodes() )
  430. _fragment.AddCopy( node );
  431. return _fragment;
  432. }
  433. /// <summary>
  434. /// 添加一个属性
  435. /// </summary>
  436. /// <param name="element">要添加属性的元素</param>
  437. /// <param name="attributeName">属性名</param>
  438. /// <param name="attributeValue">属性值</param>
  439. /// <returns>添加的属性</returns>
  440. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  441. public static IHtmlAttribute AddAttribute( this IHtmlElement element, string attributeName, string attributeValue )
  442. {
  443. if ( element == null )
  444. throw new ArgumentNullException( "element" );
  445. if ( attributeName == null )
  446. throw new ArgumentNullException( "attributeName" );
  447. var modifier = EnsureModifiable( element );
  448. return modifier.AddAttribute( element, attributeName, attributeValue );
  449. }
  450. /// <summary>
  451. /// 尝试从 DOM 中移除此节点
  452. /// </summary>
  453. /// <param name="node">要被移除的节点</param>
  454. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  455. /// <remarks>
  456. /// 若节点不存在(即为 null),则此方法不执行任何操作
  457. /// </remarks>
  458. public static void Remove( this IHtmlNode node )
  459. {
  460. if ( node == null )
  461. return;
  462. var modifier = EnsureModifiable( node );
  463. modifier.RemoveNode( node );
  464. }
  465. /// <summary>
  466. /// 尝试从 DOM 中移除指定节点
  467. /// </summary>
  468. /// <typeparam name="T">节点类型</typeparam>
  469. /// <param name="nodes">要移除的节点</param>
  470. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  471. /// <exception cref="System.InvalidOperationException">若节点不是位于同一文档</exception>
  472. public static void Remove( this IEnumerable<IHtmlNode> nodes )
  473. {
  474. if ( !nodes.Any() )
  475. return;
  476. var document = nodes.First().Document;
  477. var modifier = document.DomModifier;
  478. if ( modifier == null )
  479. throw new NotSupportedException();
  480. var array = nodes.ToArray();
  481. if ( array.Any( item => !item.Document.Equals( document ) ) )
  482. throw new InvalidOperationException();
  483. foreach ( var node in array )
  484. {
  485. modifier.RemoveNode( node );
  486. }
  487. }
  488. /// <summary>
  489. /// 尝试从 DOM 中移除此属性
  490. /// </summary>
  491. /// <param name="attribute">要被移除的属性</param>
  492. /// <exception cref="System.NotSupportedException">若文档不支持修改 DOM 结构</exception>
  493. /// <remarks>
  494. /// 若属性不存在(即为 null),则此方法不执行任何操作
  495. /// </remarks>
  496. public static void Remove( this IHtmlAttribute attribute )
  497. {
  498. if ( attribute == null )
  499. return;
  500. if ( attribute.Element == null )
  501. throw new InvalidOperationException();
  502. var modifier = EnsureModifiable( attribute.Element );
  503. modifier.RemoveAttribute( attribute );
  504. }
  505. /// <summary>
  506. /// 尝试使用指定的 HTML 碎片替换此节点
  507. /// </summary>
  508. /// <param name="node">要被替换的节点</param>
  509. /// <param name="fragment">替换节点的 HTML 碎片</param>
  510. /// <returns>碎片置入后产生的节点集</returns>
  511. /// <exception cref="System.InvalidOperationException">若节点和碎片不在同一文档</exception>
  512. public static IEnumerable<IHtmlNode> ReplaceWith( this IHtmlNode node, IHtmlFragment fragment )
  513. {
  514. if ( node == null )
  515. throw new ArgumentNullException( "node" );
  516. if ( fragment == null )
  517. throw new ArgumentNullException( "fragment" );
  518. if ( !object.Equals( fragment.Document, node.Document ) )
  519. throw new InvalidOperationException();
  520. var container = node.Container;
  521. lock ( container )
  522. {
  523. int index = node.NodesIndexOfSelf();
  524. Remove( node );
  525. return fragment.Into( container, index );
  526. }
  527. }
  528. /// <summary>
  529. /// 尝试使用指定的 HTML 文本片段替换此节点
  530. /// </summary>
  531. /// <param name="node">要被替换的节点</param>
  532. /// <param name="html">替换节点的 HTML 文本</param>
  533. /// <returns>HTML 文本置入后产生的节点集</returns>
  534. public static IEnumerable<IHtmlNode> ReplaceWithHtml( this IHtmlNode node, string html )
  535. {
  536. if ( node == null )
  537. throw new ArgumentNullException( "node" );
  538. if ( html == null )
  539. throw new ArgumentNullException( "html" );
  540. var fragment = node.Document.ParseFragment( html );
  541. return ReplaceWith( node, fragment );
  542. }
  543. /// <summary>
  544. /// 使用指定文本替换元素内容(警告,此方法会清除元素所有内容)
  545. /// </summary>
  546. /// <param name="element">要替换内容的元素</param>
  547. /// <param name="text">文本内容</param>
  548. public static T InnerText<T>( this T element, string text ) where T : IHtmlElement
  549. {
  550. return InnerText( element, text, false );
  551. }
  552. /// <summary>
  553. /// 使用指定文本替换元素内容(警告,此方法会清除元素所有内容)
  554. /// </summary>
  555. /// <param name="element">要替换内容的元素</param>
  556. /// <param name="text">文本内容</param>
  557. /// <param name="encodeWhiteSpaces">是否编码空白字符</param>
  558. public static T InnerText<T>( this T element, string text, bool encodeWhiteSpaces ) where T : IHtmlElement
  559. {
  560. if ( element == null )
  561. throw new ArgumentNullException( "element" );
  562. var modifier = EnsureModifiable( element );
  563. lock ( element.SyncRoot )
  564. {
  565. ClearNodes( element );
  566. if ( string.IsNullOrEmpty( text ) )//对于空输入,则只需要清空元素即可
  567. return element;
  568. if ( HtmlSpecification.cdataTags.Contains( element.Name, StringComparer.OrdinalIgnoreCase ) )
  569. {
  570. modifier.AddTextNode( element, text );
  571. }
  572. else if ( HtmlSpecification.preformatedElements.Contains( element.Name, StringComparer.OrdinalIgnoreCase ) || !encodeWhiteSpaces )
  573. {
  574. modifier.AddTextNode( element, HtmlEncoding.HtmlEncode( text ) );
  575. }
  576. else
  577. {
  578. var encoded = HtmlEncoding.HtmlEncode( text );
  579. encoded = encoded.Replace( " ", "&nbsp; " );
  580. encoded = encoded.Replace( "\r\n", "\n" ).Replace( "\r", "\n" );
  581. encoded = encoded.Replace( "\n", "<br />" );
  582. element.Document.ParseFragment( encoded ).Into( element, 0 );
  583. }
  584. }
  585. return element;
  586. }
  587. /// <summary>
  588. /// 使用指定的HTML文本替换元素内容(警告,此方法会清除元素所有内容)
  589. /// </summary>
  590. /// <param name="element">要替换内容的元素</param>
  591. /// <param name="html">要替换的HTML代码</param>
  592. public static T InnerHtml<T>( this T element, string html ) where T : IHtmlElement
  593. {
  594. if ( element == null )
  595. throw new ArgumentNullException( "element" );
  596. var modifier = EnsureModifiable( element );
  597. lock ( element.SyncRoot )
  598. {
  599. ClearNodes( element );
  600. if ( string.IsNullOrEmpty( html ) )//对于空输入,则只需要清空元素即可
  601. return element;
  602. if ( HtmlSpecification.cdataTags.Contains( element.Name, StringComparer.OrdinalIgnoreCase ) )
  603. {
  604. modifier.AddTextNode( element, html );
  605. }
  606. else
  607. {
  608. var fragment = element.Document.ParseFragment( html );
  609. fragment.Into( element, 0 );
  610. }
  611. }
  612. return element;
  613. }
  614. /// <summary>
  615. /// 清除所有子节点
  616. /// </summary>
  617. /// <param name="container">要清除所有子节点的元素</param>
  618. public static T ClearNodes<T>( this T container ) where T : IHtmlContainer
  619. {
  620. if ( container == null )
  621. throw new ArgumentNullException( "container" );
  622. lock ( container.SyncRoot )
  623. {
  624. var childs = container.Nodes().ToArray();//清除所有的子节点
  625. foreach ( var node in childs )
  626. node.Remove();
  627. }
  628. return container;
  629. }
  630. }
  631. }