Seleniumspørgsmål vedr. getText() - Eksperten

08. maj 2025 - 16:32 Der er kommentarer

HTML-kode:
<div class="ccc">
<ul>
<li><strong>a</strong> b c d</li>
<li><strong>a b</strong> c d</li>
<li><strong>a b c</strong> d</li>
</ul>
</div>

Java-Selenium kode:
WebElement ccc= driver.findElement(By.cssSelector("div.ccc"));
List<WebElement> ulList = ccc.findElements(By.tagName("li"));
for(int j = 0; j < ulList.size(); j++) {
  String txt = ulList.get(j).getText();
  System.out.println(ulList.get(j).getText();
}

Uddata:
a b c d
a b c d
a b c d

Forventet uddata:
<strong>a</strong> b c d
<strong>a b</strong> c d
<strong>a b c</strong> d

Spørgsmål 1:
Resultatet er "Uddata". Men som jeg har forstået getText(), så burde den returnere alt mellem <li> og </li>, dvs "Forventet uddata".
Er det muligt at få "Forventet uddata"?

Spørgsmål 2:
Det, jeg egentlig er interesseret i, er at få adskilt det, der står mellem <strong> og </strong>, og det der stå udenfor <strong>.
Hvordan gør jeg det?

Jeg håber, at spørgsmålet er i den korrekte kategori.
På forhånd tak.

Dokumentationen:

()

siger "Get the visible (i.e. not hidden by CSS) text of this element, including sub-elements".

Det kan vel godt betyde tekst uden tags.

Du må kunne finde strong indholdet via:

ulList.get(j).getElement(???)

eller:

ulList.get(j).getElements(???)

Jeg ved ikke helt hvad ??? skal være da jeg ikek kender Selenium.

Lidt hurtig eksperimenteren kom op med:

        WebElement ccc= driver.findElement(By.cssSelector("div.ccc"));
        for(WebElement li : ccc.findElements(By.tagName("li"))) {
            String txt = li.getText();
            System.out.printf("txt = %s\n", txt);
            for(WebElement elm : li.findElements(By.xpath(".//*"))) {
                System.out.printf("%s -> %s\n", elm.getTagName(), elm.getText());
            }
        }

som finder strong delen.

Desværre kan jeg ikke bruge teknikken til at hapse ikke-strong delen med da Selenium findElement(s) kun vil finde elementer ikke text.

Kan du evt. som workaround tage getText() og så fjerne alt der kommer fra sub elementerne (der jo kan findes)?

Ad #3:

Jeg finder "strong" på denne måde:
for(int j = 0; j < ulList.size(); j++) {
  String txt = ulList.get(j).getText();
  String strong = (ulList.get(j).findElement(By.tagName("strong"))).getText();
  System.out.println("strong:"+strong+", txt:"+txt);
}

Ad #5:

Ja, det er den workaround, jeg arbejder med i øjeblikket, men jeg havde forventet, at Selenium var lidt mere fleksibel.

Jeg er iøvrigt behørigt imponeret over, at du har fundet en løsning så hurtigt. Indlærlingskurven er noget stejlere på Selenium, end de fleste andre testværktøjer.

Jeg fik lige en ide.

XPath kan godt finde direkte tekst. Det er et selenium type check som driller.

Men man kan jo skifte til ren XML parsing!

    public static String grabNonElementText(String xmlstr) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new InputSource(new StringReader("<fake>" + xmlstr + "</fake>")));
        XPath xpath = XPathFactory.newInstance().newXPath();
        return (String)xpath.evaluate("text()", doc.getDocumentElement(), XPathConstants.STRING);
    }
...
        WebElement ccc= driver.findElement(By.cssSelector("div.ccc"));
        for(WebElement li : ccc.findElements(By.tagName("li"))) {
            String txt = li.getText();
            System.out.printf("txt = %s\n", txt);
            for(WebElement elm : li.findElements(By.xpath(".//*"))) {
                System.out.printf("%s -> %s\n", elm.getTagName(), elm.getText());
            }
            String html = li.getDomProperty("innerHTML");
            System.out.println(html);
            String dirtxt = grabNonElementText(html);
            System.out.println(dirtxt);
        }

Ja - det er ogs[ et hack, men måske lidt pænere.

Eller hvis der er flere text segmenter.

    public static List<String> grabNonElementTexts(String xmlstr) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new InputSource(new StringReader("<fake>" + xmlstr + "</fake>")));
        XPath xpath = XPathFactory.newInstance().newXPath();
        NodeList n = (NodeList)xpath.evaluate("text()", doc.getDocumentElement(), XPathConstants.NODESET);
        List<String> res = new ArrayList<String>();
        for(int i = 0; i < n.getLength(); i++) {
            res.add(((Text)n.item(i)).getData());
        }
        return res;
    }

XML parsing er udelukket.
Det er en del af en omfattende regressionstest, så jeg er bundet til Selenium.

Selenium er iøvrigt udmærket til regresstionstest. Jeg har stærkt på fornemmelsen, at der er en bedre måde at gøre det på, og det generer mig, at jeg ikke kan finde den "rigtige" løsning.

På et tidspunkt, når testen er færdig, så er der sikkert en, der spørger: Hvorfor gjorde du ikke bare..., og så siger jeg Nååh ja, hvorfor tænkte jeg ikke på det...

.getDomProperty("innerHTML") som henter den rå HTML mellem <li> og </li> ud er Selenium.

Det er så bare hvordan man parser den rå HTML. XML parser er indbygget i Java og er en robust løsning, men der der er andre måder at lave den parse på.

Hvad med en helt banal split?

        WebElement ccc= driver.findElement(By.cssSelector("div.ccc"));
        for(WebElement li : ccc.findElements(By.tagName("li"))) {
            String txt = li.getText();
            System.out.printf("txt = %s\n", txt);
            for(WebElement elm : li.findElements(By.xpath(".//*"))) {
                System.out.printf("%s -> %s\n", elm.getTagName(), elm.getText());
            }
            String html = li.getDomProperty("innerHTML");
            System.out.println(html);
            for(String dirtxt : html.split("<.+?>.*?</.+?>")) {
                if(dirtxt.length() > 0) {
                    System.out.println(dirtxt);
                }
            }
        }

Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Følg dette spørgsmål

Opret Preview

Kategori

Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester