Avatar billede mergelspir Seniormester
08. maj 2025 - 16:32 Der er 11 kommentarer

Seleniumspørgsmål vedr. getText()

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.
Avatar billede arne_v Ekspert
08. maj 2025 - 16:51 #1
Dokumentationen:

https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/WebElement.html#getText()

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.
Avatar billede arne_v Ekspert
08. maj 2025 - 16:53 #2
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.
Avatar billede arne_v Ekspert
08. maj 2025 - 19:07 #3
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.
Avatar billede arne_v Ekspert
08. maj 2025 - 19:09 #5
Kan du evt. som workaround tage getText() og så fjerne alt der kommer fra sub elementerne (der jo kan findes)?
Avatar billede mergelspir Seniormester
08. maj 2025 - 19:50 #6
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.
Avatar billede arne_v Ekspert
08. maj 2025 - 20:45 #7
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.
Avatar billede arne_v Ekspert
08. maj 2025 - 21:02 #8
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;
    }
Avatar billede mergelspir Seniormester
08. maj 2025 - 21:27 #9
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...
Avatar billede arne_v Ekspert
08. maj 2025 - 22:10 #10
.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å.
Avatar billede arne_v Ekspert
08. maj 2025 - 22:16 #11
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);
                }
            }
        }
Avatar billede 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.

Loading billede 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







OSZAR »