Ejemplo de código que utiliza HTMLAgilitypack para seleccionar nodos ASPX por xpath

html-agility-pack

Pregunta

Me gustaría saber por qué mi código no funciona (o, obtener un fragmento de código de muestra funcional )

Lo que estoy tratando de hacer es consultar un archivo ASPX usando el HTMLAgilityPack, por una expresión XPATH

Este es el código, si ingresa // asp: content , tiene 0 nodos (Form1.designer.cs omitido para mayor claridad):

using hap = HtmlAgilityPack;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Windows.Forms;

namespace hap_shell
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            lbl_ErrMsg.Text = "";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                lbl_ErrMsg.Text = "";
                hap.HtmlDocument doc = new hap.HtmlDocument();
                hap.HtmlWeb hw = new hap.HtmlWeb();

                doc.Load(txt_FilePath.Text);

                var q = doc.DocumentNode.Descendants("asp:Content");
                var cnt = q.Count();
                var nodes = q.ToList();
                var nav = doc.CreateNavigator();
                System.Xml.XmlNamespaceManager mgr = new System.Xml.XmlNamespaceManager(nav.NameTable);
                mgr.AddNamespace("asp",  "http://www.w3.org/1999/xhtml/"); // "http://tempuri.org/foo");
                var selNodes =nav.Select(txt_xpath.Text, mgr);


                //var selNodes = doc.DocumentNode.SelectNodes(txt_xpath.Text);

                if (selNodes == null)
                {
                    lbl_ErrMsg.Text = "No nodes match your query.";
                }
                lbl_ErrMsg.Text = selNodes.Count.ToString() + " nodes selected";
            }
            catch (Exception ex)
            {
                lbl_ErrMsg.Text = (ex.Message);
            }

        }
    }
}

esta es la prueba aspx, guárdela en un archivo e ingrese su ruta completa a txt_FilePath:

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="back_cal.aspx.cs" Inherits="EDP_SYS.back_cal" %>
    <asp:content id="Content1" contentplaceholderid="HeadContent" runat="server" >
        </asp:content>
        <asp:content id="Content2" contentplaceholderid="MainContent" runat="server">
         <table>

                <tr><td>
                <asp:button id="Button1" runat="server" text="Search"></asp:button></td></tr>

               </table> 
        </asp:content>

Nota:

  1. Sé que agregar el espacio de nombres http://www.w3.org/1999/xhtml/ no tiene sentido, por favor avise la forma correcta de agregar el espacio de nombres
  2. Funciona cuando la entrada es // tr, // td etc
  3. doc.DocumentNode.Descendants ("asp: Content") funciona, pero debo aceptar un XPath de entrada de usuario, por lo que no se considerará (igual para LiNQ para XML)

Respuesta aceptada

Desafortunadamente, no pude hacer que XmlNamespaceManager funcione correctamente con HtmlAgilityPack. Pero puede usar la función xpath name() para consultar nodos asp: -like. Ver:

var contentNodes = doc.DocumentNode.SelectNodes("//*[name()='asp:content']");

Esto devolverá 2 nodos asp:content de tu fragmento.

Pero el uso de LINQ to XML es mucho más fácil para esto.



Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow