Estiven no desenvolvemento front-end o tempo suficiente para ver unha tendencia ao longo dos anos: os desenvolvedores máis novos traballan cun novo paradigma de programación sen comprender o contexto histórico da mesma. Por suposto, é perfectamente comprensible non saber algo. A web é un lugar moi grande cun conxunto diverso de habilidades e especialidades, e non sempre sabemos o que non sabemos. Aprender neste campo é unha viaxe continua en lugar de algo que ocorre unha vez e remata. Caso en cuestión: alguén do meu equipo preguntou se era posible saber se os usuarios navegan fóra dunha pestana determinada na IU. Apuntei o evento antes de descargar JavaScript. Pero os que xa abordaron isto antes saben que isto é posible porque recibiron alertas sobre datos non gardados noutros sitios, para os que antes de descargar é un caso de uso típico. Tamén indiquei a páxina Ocultar e visibilidade Cambiar eventos ao meu colega para boa medida. Como souben iso? Porque xurdiu noutro proxecto, non porque estudei sobre el cando aprendín inicialmente JavaScript. O feito é que os frameworks front-end modernos están sobre os ombreiros dos xigantes da tecnoloxía que os precederon. Abstraen as prácticas de desenvolvemento, moitas veces para unha mellor experiencia do programador que reduce, ou mesmo elimina, a necesidade de coñecer ou tocar os que tradicionalmente foron conceptos front-end esenciais que todos probablemente deberían coñecer. Considere o modelo de obxectos CSS (CSSOM). Podería esperar que calquera que traballe en CSS e JavaScript teña unha chea de experiencia práctica en CSSOM, pero non sempre será así. Houbo un proxecto React para un sitio de comercio electrónico no que traballei onde necesitabamos cargar unha folla de estilo para o provedor de pago seleccionado actualmente. O problema era que a folla de estilo cargaba en todas as páxinas cando só se necesitaba nunha páxina específica. O programador encargado de que isto ocorrese nunca cargara unha folla de estilo dinámicamente. De novo, isto é totalmente comprensible cando React abstrae o enfoque tradicional que podería ter alcanzado. É probable que o CSSOM non sexa algo que necesites no teu traballo diario. Pero é probable que teñas que interactuar con el nalgún momento, mesmo nunha instancia puntual. Estas experiencias inspiráronme a escribir este artigo. Hai moitas funcións web e tecnoloxías existentes en estado salvaxe que quizais nunca toques directamente no teu traballo diario. Quizais sexas bastante novo no desenvolvemento web e simplemente non os coñezas porque estás metido na abstracción dun marco específico que non require que o coñezas a fondo, nin sequera. Estou falando especificamente de XML, que moitos sabemos que é unha linguaxe antiga non totalmente diferente do HTML. Estou mencionando isto debido ás recentes discusións de WHATWG que suxiren que unha parte importante da pila XML coñecida como programación XSLT debería eliminarse dos navegadores. Este é exactamente o tipo de tecnoloxía máis antiga e existente que tivemos durante anos que podería usarse para algo tan práctico como a situación CSSOM na que se atopaba o meu equipo. Xa traballaches con XSLT antes? A ver se nos apoiamos moito nesta tecnoloxía máis antiga e aproveitamos as súas funcións fóra do contexto de XML para abordar os problemas do mundo real actual. XPath: a API central A tecnoloxía XML máis importante que quizais sexa a máis útil fóra dunha perspectiva XML directa é XPath, unha linguaxe de consulta que permite atopar calquera nodo ou atributo nunha árbore de marcas cun elemento raíz. Teño un cariño persoal por XSLT, pero iso tamén depende de XPath, e o cariño persoal debe deixarse ​​de lado na importancia da clasificación. O argumento para eliminar XSLT non fai ningunha mención a XPath, polo que supoño que aínda está permitido. Isto é bo porque XPath é a API central e máis importante deste conxunto de tecnoloxías, especialmente cando se intenta atopar algo para usar fóra do uso normal de XML. É importante porque, aínda que os selectores CSS poden usarse para atopar a maioría dos elementos da túa páxina, non poden atopalos todos. Ademais, os selectores CSS non se poden usar para atopar un elemento en función da súa posición actual no DOM. XPath pode. Agora, algúns de vostedes que lean isto quizais coñezan XPath e outros non. XPath é unha área tecnolóxica bastante grande e non podo ensinar todos os conceptos básicos nin mostrarche cousas interesantes para facer con el nun único artigo coma este. En realidade tentei escribir ese artigo, pero a publicación media de Smashing Magazine non supera as 5.000 palabras. Xa estaba en máis de2.000 palabras mentres só a metade do básico. Entón, vou comezar a facer cousas interesantes con XPath e darche algunhas ligazóns que podes usar para o básico se atopas estas cousas interesantes. Combinando XPath e CSS XPath pode facer moitas cousas que os selectores CSS non poden cando consultan elementos. Pero os selectores CSS tamén poden facer algunhas cousas que XPath non pode, é dicir, consultar elementos polo nome da clase.

CSS XPath .myClass /*[contén(@clase, "a miñaClase")]

Neste exemplo, CSS consulta elementos que conteñan un nome de clase .myClass. Mentres tanto, o exemplo XPath consulta elementos que conteñan unha clase de atributo coa cadea "myClass". Noutras palabras, selecciona elementos con myClass en calquera atributo, incluídos os elementos co nome de clase .myClass, así como elementos con "myClass" na cadea, como .myClass2. XPath é máis amplo nese sentido. Entón, non. Non estou suxindo que debamos botar CSS e comezar a seleccionar todos os elementos a través de XPath. Ese non é o punto. A cuestión é que XPath pode facer cousas que CSS non poden e aínda poden ser moi útiles, aínda que é unha tecnoloxía máis antiga na pila do navegador e pode non parecer obvio a primeira vista. Usemos as dúas tecnoloxías xuntas non só porque podemos, senón porque aprenderemos algo sobre XPath durante o proceso, converténdoo nunha ferramenta máis da túa pila, unha que quizais non sabías que estivo alí todo o tempo. O problema é que o método document.evaluate de JavaScript e os distintos métodos de selección de consulta que usamos coas API de CSS para JavaScript son incompatibles. Fixen unha API de consulta compatible para comezar, aínda que hai que admitir que non pensei moito nela xa que é unha diferenza do que estamos facendo aquí. Aquí tes un exemplo de traballo bastante sinxelo dun construtor de consulta reutilizable: Vexa o Pen queryXPath [forked] de Bryan Rasmussen. Engadín dous métodos ao obxecto do documento: queryCSSSelectors (que é esencialmente querySelectorAll) e queryXPaths. Ambos devolven un obxecto queryResults:

{ queryType: nodos | cadea | número | booleano, resultados: calquera[] // elementos html, elementos xml, cadeas, números, booleanos, queryCSSSelectors: (consulta: cadea, modificar: booleano) => queryResults, queryXpaths: (query: string, amend: boolean) => queryResults }

As funcións queryCSSSelectors e queryXpaths executan a consulta que lles proporcionas sobre os elementos da matriz de resultados, sempre que a matriz de resultados sexa do tipo nodos, por suposto. En caso contrario, devolverá un queryResult cunha matriz baleira e un tipo de nós. Se a propiedade de modificación está definida como verdadeira, as funcións cambiarán os seus propios queryResults. En ningún caso debe utilizarse nun ambiente de produción. Fágoo deste xeito unicamente para demostrar os diversos efectos de usar as dúas API de consulta xuntas. Consultas de exemplo Quero mostrar algúns exemplos de diferentes consultas XPath que demostran algunhas das cousas poderosas que poden facer e como se poden usar en lugar doutros enfoques. O primeiro exemplo é //li/text(). Isto consulta todos os elementos li e devolve os seus nodos de texto. Entón, se tivesemos que consultar o seguinte HTML:

  • un
  • dous
  • tres

... isto é o que se devolve:

{"queryType":"xpathEvaluate","results":["un","dous","tres"],"resultType":"cadea"}

Noutras palabras, obtemos a seguinte matriz: ["un","dous","tres"]. Normalmente, consultaría os elementos li para obtelo, convertería o resultado desa consulta nunha matriz, mapearía a matriz e devolvería o nodo de texto de cada elemento. Pero podemos facelo de forma máis concisa con XPath: document.queryXPaths("//li/text()").results.

Teña en conta que a forma de obter un nodo de texto é usar text(), que parece unha sinatura de función, e así é. Devolve o nodo de texto dun elemento. No noso exemplo, hai tres elementos li no marcado, cada un contén texto ("un", "dous" e "tres"). Vexamos un exemplo máis dunha consulta text(). Supoñamos que este é o noso marcado: Iniciar sesión

Escribamos unha consulta que devolva o valor do atributo href: document.queryXPaths("//a[text() = 'Iniciar sesión']/@href").results.

Esta é unha consulta XPath no documento actual, igual que no último exemplo, pero esta vez devolvemos o atributo href dunha ligazón (un elemento) que contén o texto "Iniciar sesión". O real devoltoo resultado é ["/login.html"]. Visión xeral das funcións de XPath Hai unha serie de funcións XPath e probablemente non esteas familiarizado con elas. Creo que hai varios que paga a pena coñecer, incluíndo os seguintes:

starts-withSe un texto comeza cun outro exemplo de texto concreto, starts-with(@href, 'http:') devolve verdadeiro se un atributo href comeza por http:. containsSe un texto contén outro exemplo de texto concreto, contains(text(), "Smashing Magazine") devolve verdadeiro se un nodo de texto contén as palabras "Smashing Magazine" en calquera lugar. countDevolve un reconto de cantas coincidencias hai nunha consulta. Por exemplo, count(//*[starts-with(@href, 'http:']) devolve un reconto de cantas ligazóns no nodo de contexto teñen elementos cun atributo href que contén o texto que comeza por http:. subcadeaFunciona como a subcadea de JavaScript, excepto que pasas a cadea como argumento. Por exemplo, subcadea("meu texto", 2, 4) devolve "y t". substring-before Devolve a parte dunha cadea antes doutra cadea. Por exemplo, substing-before("meu texto", " ") devolve "meu". Do mesmo xeito, substring-before("ola","bye") devolve unha cadea baleira. substring-afterDevolve a parte dunha cadea despois doutra cadea. Por exemplo, substing-after("meu texto", " ") devolve "texto". Do mesmo xeito, substring-after("ola","bye") devolve unha cadea baleira. normalize-spaceDevolve a cadea de argumentos cos espazos en branco normalizados eliminando os espazos en branco principais e ao final e substituíndo as secuencias de caracteres de espazos en branco por un único espazo. notDevolve un booleano verdadeiro se o argumento é falso, se non é falso. trueReturns booleano verdadeiro. falseReturns booleano falso. concatO mesmo que JavaScript concat, excepto que non o executas como método nunha cadea. Pola contra, pon todas as cadeas que queres concatenar. string-lengthThis non é o mesmo que JavaScript string-length, senón que devolve a lonxitude da cadea que se dá como argumento. translateThis toma unha cadea e cambia o segundo argumento polo terceiro argumento. Por exemplo, translate("abcdef", "abc", "XYZ") produce XYZdef.

Ademais destas funcións particulares de XPath, hai unha serie de outras funcións que funcionan igual que as súas contrapartes de JavaScript - ou homólogos basicamente en calquera linguaxe de programación - que probablemente tamén che resulten útiles, como chan, teito, redondo, suma, etc. A seguinte demostración ilustra cada unha destas funcións: Vexa as funcións numéricas de Pen XPath [forked] de Bryan Rasmussen. Teña en conta que, como a maioría das funcións de manipulación de cadeas, moitas das numéricas levan unha única entrada. Isto é, por suposto, porque se supón que se usan para realizar consultas, como no último exemplo XPath: //li[piso(texto()) > 250]/@val

Se os usas, como fan a maioría dos exemplos, acabarás executándoo no primeiro nodo que coincida coa ruta. Tamén hai algunhas funcións de conversión de tipos que probablemente deberías evitar porque JavaScript xa ten os seus propios problemas de conversión de tipos. Pero pode haber momentos nos que queiras converter unha cadea nun número para comparalo con outro número. As funcións que definen o tipo de algo son booleano, número, cadea e nodo. Estes son os tipos de datos XPath importantes. E como podes imaxinar, a maioría destas funcións pódense usar en tipos de datos que non son nós DOM. Por exemplo, substring-after toma unha cadea como xa explicamos, pero pode ser a cadea dun atributo href. Tamén pode ser só unha cadea:

const testSubstringAfter = document.queryXPaths("substring-after('hola mundo',' ')");

Obviamente, este exemplo devolveranos a matriz de resultados como ["mundo"]. Para mostrar isto en acción, fixen unha páxina de demostración usando funcións contra cousas que non son nodos DOM: Vexa o Pen queryXPath [forked] de Bryan Rasmussen. Deberías ter en conta o aspecto sorprendente da función de tradución, que é que se tes un carácter no segundo argumento (é dicir, a lista de caracteres que queres traducir) e ningún carácter coincidente ao que traducir, ese carácter eliminarase da saída. Así, isto:

translate('Ola, chámome Inigo Montoya, mataches a meu pai, prepárate para morrer','abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,','*')

…resulta na cadea, incluíndo espazos: [" ** ** "]

Isto significa que a letra "a" está a ser traducida a un asterisco (*), pero todos os demais caracteres que non teñan tradución dada a cadea de destino son completamente eliminados. O espazo en branco é o único que nos quedaentre os caracteres "a" traducidos. De novo, esta consulta:

translate('Ola, chámome Inigo Montoya, mataches a meu pai, prepárate para morrer','abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,','****************************************************')")

... non ten o problema e dá como resultado un resultado así:

"****** ** **** ** ***** ******* *** ****** ** ****** ******* ** ***"

Poderíache chamar a atención que non hai un xeito sinxelo en JavaScript de facer exactamente o que fai a función de tradución XPath, aínda que para moitos casos de uso, substituírAll con expresións regulares pode xestionalo. Poderías usar o mesmo enfoque que demostrei, pero iso non é óptimo se o único que queres é traducir as cadeas. A seguinte demostración inclúe a función de tradución de XPath para proporcionar unha versión de JavaScript: Vexa a función de tradución Pen [forked] de Bryan Rasmussen. Onde podes usar algo así? Considere o cifrado Caesar Cipher cunha compensación de tres lugares (por exemplo, o cifrado superior do 48 a.C.):

translate("¡César planea cruzar o Rubicón!", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "XYZABCDEFGHIJKLMNOPQRSTUVWxyzabcdefghijklmnopqrstuvw")

O texto de entrada "César planea cruzar o Rubicón!" resulta en "Zxbpxo fp mixkkfkd ql zolpp qeb Oryfzlk!" Para dar outro exemplo rápido de diferentes posibilidades, fixen unha función metálica que toma unha entrada de cadea e usa unha función de tradución para devolver o texto, incluíndo todos os caracteres que levan diéresis. Vexa a función Pen metal [forked] de Bryan Rasmussen.

const metal = (str) => { return translate(str, "AOUaou","ÄÖÜäöü"); }

E, se se dá o texto "Motley Crue rules, rock on dudes!", devolve "Mötley Crüe rüles, röck ön düdes!" Obviamente, pódese ter todo tipo de usos parodiais desta función. Se es ti, entón este artigo de TVTropes debería proporcionarche moita inspiración. Usando CSS con XPath Lembra o noso motivo principal para usar os selectores CSS xunto con XPath: CSS entende bastante o que é unha clase, mentres que o mellor que podes facer con XPath son as comparacións de cadeas do atributo de clase. Iso funcionará na maioría dos casos. Pero se algunha vez te atopases nunha situación na que, por exemplo, alguén crease clases chamadas .primaryLinks e .primaryLinks2 e estiveses a usar XPath para obter a clase .primaryLinks, é probable que tes problemas. Mentres non haxa nada parvo como iso, probablemente usarías XPath. Pero é triste informar que traballei en lugares onde a xente fai ese tipo de parvadas. Aquí tes outra demostración usando CSS e XPath xuntos. Mostra o que ocorre cando usamos o código para executar un XPath nun nodo de contexto que non é o nodo do documento. Vexa o Pen css e xpath xuntos [forked] de Bryan Rasmussen. A consulta CSS é .relatedarticles a, que obtén os dous elementos a nun div asignado a unha clase .relatedarticles. Despois hai tres consultas "malas", é dicir, consultas que non fan o que queremos que fagan cando se executan con estes elementos como nodo de contexto. Podo explicar por que se comportan de forma diferente do que poderías esperar. As tres consultas incorrectas en cuestión son:

//text(): Devolve todo o texto do documento. //a/text(): Devolve todo o texto dentro das ligazóns do documento. ./a/text(): non devolve ningún resultado.

O motivo destes resultados é que, aínda que o seu contexto é un elemento devolto da consulta CSS, // vai contra todo o documento. Esta é a forza de XPath; CSS non pode pasar dun nodo a un antepasado e despois a un irmán dese antepasado e baixar a un descendente dese irmán. Pero XPath pode. Mentres tanto, ./ consulta os fillos do nodo actual, onde o punto (.) representa o nodo actual e a barra inclinada (/) representa ir a algún nodo fillo; se é un atributo, elemento ou texto está determinado pola seguinte parte do camiño. Pero non hai ningún elemento fillo seleccionado pola consulta CSS, polo que esa consulta tampouco devolve nada. Hai tres boas consultas nesta última demostración:

.//texto(), ./text(), normalizar-espazo(./texto()).

A consulta de normalización de espazo demostra o uso da función XPath, pero tamén soluciona un problema incluído nas outras consultas. O HTML está estruturado así:

Automatiza a túa proba de funcións con Selenium WebDriver

A consulta devolve un avance de liña ao principio e ao final do nodo de texto,e normalize-space elimina isto. Usar calquera función XPath que devolva algo que non sexa un booleano cunha entrada XPath aplícase a outras funcións. A seguinte demostración mostra unha serie de exemplos: Vexa os exemplos de funcións Pen xpath [forked] de Bryan Rasmussen. O primeiro exemplo mostra un problema que debes ter en conta. En concreto, o seguinte código:

document.queryXPaths("substring-after(//a/@href,'https://')");

…devolve unha cadea:

"www.smashingmagazine.com/2018/04/feature-testing-selenium-webdriver/"

Ten sentido, non? Estas funcións non devolven matrices senón cadeas ou números únicos. Executar a función en calquera lugar con varios resultados só devolve o primeiro resultado. O segundo resultado mostra o que realmente queremos:

document.queryCSSSelectors("a").queryXPaths("substring-after(./@href,'https://')");

O que devolve unha matriz de dúas cadeas:

["www.smashingmagazine.com/2018/04/feature-testing-selenium-webdriver/","www.smashingmagazine.com/2022/11/automated-test-results-improve-accessibility/"]

As funcións XPath pódense aniñar igual que as funcións en JavaScript. Entón, se coñecemos a estrutura do URL de Smashing Magazine, poderiamos facer o seguinte (recoméndase usar literal de modelo): `traducir( subcadea( substring-after(./@href, 'www.smashingmagazine.com/') ,9), '/','')'

Isto faise un pouco demasiado complexo na medida en que necesita comentarios que describan o que fai: tome todo o URL do atributo href despois de www.smashingmagazine.com/, elimine os nove primeiros caracteres e, a continuación, traduca o carácter da barra diagonal (/) a nada para desfacerse da barra inclinada final. A matriz resultante:

["feature-testing-selenium-webdriver","resultados-de-probas-automatizados-mellorar-a-accesibilidade"]

Máis casos de uso de XPath XPath realmente pode brillar nas probas. O motivo non é difícil de ver, xa que XPath pódese usar para obter todos os elementos do DOM, desde calquera posición do DOM, mentres que CSS non. Non pode contar con que as clases CSS sigan sendo consistentes en moitos sistemas de compilación modernos, pero con XPath, podemos facer coincidencias máis sólidas sobre cal é o contido de texto dun elemento, independentemente da estrutura DOM cambiante. Houbo investigacións sobre técnicas que permiten facer probas XPath resistentes. Nada é peor que que as probas se desfagan e fallen só porque un selector CSS xa non funciona porque se cambiou o nome ou eliminou algo. XPath tamén é xenial na extracción de múltiples localizadores. Hai máis dunha forma de usar consultas XPath para facer coincidir un elemento. O mesmo ocorre con CSS. Pero as consultas XPath poden explorar as cousas dun xeito máis específico que limita o que se devolve, o que lle permite atopar unha coincidencia específica onde pode haber varias coincidencias posibles. Por exemplo, podemos usar XPath para devolver un elemento h2 específico que está contido dentro dun div que segue inmediatamente a un div irmán que, á súa vez, contén un elemento de imaxe fillo cun atributo data-testID="leader":

non recibe este título

Tampouco tes este título

A cabeceira da imaxe líder

Esta é a consulta: document.queryXPaths(` //div[ seguinte irmán::div[1] /img[@data-testID='líder'] ] /h2/ texto() `);

Imos lanzar unha demostración para ver como todo se xunta: Vexa a consulta Pen Complex H2 [forked] de Bryan Rasmussen. Entón, si. Hai moitos camiños posibles a calquera elemento nunha proba usando XPath. XSLT 1.0 Obsoleto Mencionei ao principio que o equipo de Chrome planea eliminar a compatibilidade con XSLT 1.0 do navegador. Isto é importante porque XSLT 1.0 usa programación enfocada en XML para a transformación de documentos que, á súa vez, depende de XPath 1.0, que é o que se atopa na maioría dos navegadores. Cando isto suceda, perderemos un compoñente clave de XPath. Pero dado o feito de que XPath é realmente xenial para escribir probas, paréceme improbable que o XPath no seu conxunto desapareza pronto. Dito isto, notei que a xente se interesa por unha función cando se quita. E iso é certamente certo no caso de que XSLT 1.0 estea obsoleto. Hai toda unha discusión en Hacker News chea de argumentos en contra da desaprobación. A publicación en si é un gran exemplo de creación dun marco de blogs con XSLT. Tipode ler a discusión por si mesmo, pero infórmase de como se pode usar JavaScript como calceta para XLST para xestionar ese tipo de casos. Tamén vin suxestións de que os navegadores deberían usar SaxonJS, que é un porto para os motores Saxon XSLT, XQUERY e XPath de JavaScript. Esa é unha idea interesante, especialmente porque Saxon-JS implementa a versión actual destas especificacións, mentres que non hai ningún navegador que implemente ningunha versión de XPath ou XSLT máis aló da 1.0, nin ningún que implemente XQuery. Contactei con Norm Tovey-Walsh en Saxonica, a empresa detrás de SaxonJS e outras versións do motor Saxon. El dixo: "Se algún provedor de navegadores estaba interesado en tomar SaxonJS como punto de partida para integrar tecnoloxías XML modernas no navegador, estaríamos encantados de discutilo con eles." - Norm Tovey-Walsh

Pero tamén engadiu: "Sorprenderíame moito se alguén pensase que tomar SaxonJS na súa forma actual e deixalo na compilación do navegador sen cambios sería o enfoque ideal. Un vendedor de navegadores, pola natureza do feito de que constrúe o navegador, podería abordar a integración a un nivel moito máis profundo do que podemos 'desde fóra'. "- Norm Tovey-Walsh

Paga a pena notar que os comentarios de Tovey-Walsh chegaron aproximadamente unha semana antes do anuncio de desaprobación de XSLT. Conclusión Podería seguir e seguir. Pero espero que isto demostre o poder de XPath e che dea moitos exemplos que demostren como usalo para conseguir grandes cousas. É un exemplo perfecto de tecnoloxía máis antiga na pila de navegadores que aínda ten moita utilidade hoxe en día, aínda que nunca soubeses que existía ou nunca pensaches en buscala. Lecturas complementarias

"Mellorar a resiliencia das probas web automatizadas con linguaxe natural" (Biblioteca dixital ACM) de Maroun Ayli, Youssef Bakouny, Nader Jalloul e Rima Kilany. Este artigo ofrece moitos exemplos de XPath para escribir probas de resistencia. XPath (MDN) Este é un excelente lugar para comezar se queres unha explicación técnica que detalle como funciona XPath. XPath Tutorial (ZVON)Creo que este tutorial é o máis útil para a miña propia aprendizaxe, grazas a unha gran cantidade de exemplos e explicacións claras. XPatherEsta ferramenta interactiva permíteche traballar directamente co código.

You May Also Like

Enjoyed This Article?

Get weekly tips on growing your audience and monetizing your content — straight to your inbox.

No spam. Join 138,000+ creators. Unsubscribe anytime.

Create Your Free Bio Page

Join 138,000+ creators on Seemless.

Get Started Free