Let's say I have a webpage that I need to have some selenium script to automate the UI testing. This page has a list of sections, in the order of "Section A", "Section B", "Section C", etc. Here is my piece of code to automate the steps on "Section B" area testing.
by = By.CSS_SELECTOR
dropdown_in_SectionB = "#app > div.app > div > div > div.content > div:nth-child(2) > div > div:nth-child(7) > ..."
WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((by, target))).click()
Unfortunately, I can not find a XPATH value for this "drowdown_in_SectionB" area, and I have to use css_selector value here. And it works ok for this second.
But later on, this page has been updated, the updated page now contains "Section A", "SectionX", "Section B", "Section C", in such order. And my above script is broken, as the css_selector value of drowpdown_in_Section becomes:
dropdown_in_SectionB = #app > div.app > div > div > div.content > div:nth-child(2) > div > div:nth-child(8) > ..."
So I have to update the script to have it back to working, which is annoyed.
My question is how may I find a way that the script is smart enough to locate the location in its "css_selector" value, however the change is ?
If it was of XPATH value, I can easily have it solved, as I have other clues to trace the dropdown area in Section, but how this can be done in case of css_selector value ???
Thanks,
Jack
The purpose of this is to extract list of field names from the XML (of Adobe LiveCycle Designer). So, I created the fields in designer, then, I copy the XML of the related fields, paste in Notepad++, and then executer find/replace (ctrl-h) to get only the field names, one field in each line.
This will make it then easier to write the SQL statements to add such fields to the DB to register them.
The XML looks like the following:
<field xmlns="http://www.xfa.org/schema/xfa-template/2.8/" y="0in" x="0.343mm" w="8.881pt" h="9.108pt" name="detcon_recreation_only">
<ui>
<checkButton size="8.881pt">
<border>
<edge stroke="lowered"/>
<fill/>
</border>
</checkButton>
</ui>
<font size="0pt" typeface="Adobe Pi Std"/>
<para vAlign="middle"/>
<value>
<text>0</text>
</value>
<items>
<text>1</text>
<text>0</text>
<text/>
</items>
</field>
<field xmlns="http://www.xfa.org/schema/xfa-template/2.8/" name="detcon_special_housing" y="5.393mm" w="27.94mm" h="4.134mm" x="0.343mm">
<ui>
<choiceList>
<border>
<edge stroke="lowered"/>
</border>
<margin/>
</choiceList>
</ui>
<font typeface="Arial Narrow" size="6pt"/>
<margin topInset="0mm" bottomInset="0mm" leftInset="0mm" rightInset="0mm"/>
<para vAlign="middle"/>
<value>
<text>NA</text>
</value>
<items>
<text>Not Applicable</text>
<text>Hotel Component</text>
</items>
<items save="1" presence="hidden">
<text>NA</text>
<text>HC</text>
</items>
</field>
<exclGroup xmlns="http://www.xfa.org/schema/xfa-template/2.8/" name="detcon_photo_taken" x="0in" y="0in">
<?templateDesigner itemValuesSpecified 1?>
<field w="12.446mm" h="3.825mm" name="lb_yes">
<ui>
<checkButton size="1.7639mm" shape="round">
<border>
<?templateDesigner StyleID apcb1?>
<edge/>
<fill/>
</border>
</checkButton>
</ui>
<font typeface="Myriad Pro"/>
<margin leftInset="1mm" rightInset="1mm"/>
<para vAlign="middle"/>
<caption placement="right" reserve="7.698mm">
<para vAlign="middle" spaceAbove="0pt" spaceBelow="0pt" textIndent="0pt" marginLeft="0pt" marginRight="0pt"/>
<font size="8pt" typeface="Arial Narrow" baselineShift="0pt"/>
<value>
<text>YES</text>
</value>
</caption>
<value>
<text xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</value>
<items>
<text>1</text>
</items>
</field>
<field w="28.702mm" h="3.825mm" name="lb_no" x="13.233mm">
<ui>
<checkButton size="1.7639mm" shape="round">
<border>
<?templateDesigner StyleID apcb1?>
<edge/>
<fill/>
</border>
</checkButton>
</ui>
<font typeface="Myriad Pro"/>
<margin leftInset="1mm" rightInset="1mm"/>
<para vAlign="middle"/>
<caption placement="right" reserve="23.954mm">
<para vAlign="middle" spaceAbove="0pt" spaceBelow="0pt" textIndent="0pt" marginLeft="0pt" marginRight="0pt"/>
<font size="8pt" typeface="Arial Narrow" baselineShift="0pt"/>
<value>
<text>NO (see comments)</text>
</value>
</caption>
<value>
<text xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</value>
<items>
<text>0</text>
</items>
</field>
<border>
<edge presence="hidden"/>
</border>
<?templateDesigner expand 1?></exclGroup>
So I figured out the following RegEx to perform find/replace to get only the field names, one field on each line.
Find to get Field Name: (?i)<(field|exclGroup).*name="([a-z_]\w*)".*$
Replace: $2
Another find/replace...
Remove all other lines: ^.*<(?!.*name=).*.*[\r\n]*
Replace with blank
If you execute the above two find/replace sessions, you will end up with list of field names one field per line.
What I wanted to do is to perform the above in one find/replace session, and then convert the above into SQL Statements using also find/replace, using this template:
INSERT INTO table_name (element_id, element_name, element_type, default_value, required, clone)
VALUES (12345,"field_name_goes_here","/Tx", "", "N", "Y"),
VALUES (12346,"field_name_goes_here","/Tx", "", "N", "Y"),
VALUES (12347,"field_name_goes_here","/Tx", "", "N", "Y"),
VALUES (12348,"field_name_goes_here","/Tx", "", "N", "Y"),
VALUES (12349,"field_name_goes_here","/Tx", "", "N", "Y"),
The element_id field is sequential, but don't worry about that, I can take care of this in Excel.
Appreciate your help,
Tarek
Scraper Series
One small help. The element is slightly different than the which is making things a little more complicated. Your RegEx is so sophisticated, I couldn't modify it to include the element. I think I need more time to digest it. So could you modify it to include exclGroup and only extract name only without extracting the inner field elements of the exclGroup?
Ok, here you go.
It does make it a little more complicated.
I have 2 versions to do this. One that uses recursion, one that doesn't.
I'm posting the version that uses recursion.
If you need the non-recursion, let me know and I'll post that.
Find (?:(?!<(?:field|exclGroup)(?!\w)(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+>)[\S\s])*(?><(field|exclGroup)(?=(?:[^>"']|"[^"]*"|'[^']*')*?\sname\s*=\s*(?:(['"])([\S\s]*?)\2))\s+(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+>)(?:(?&core)|)</\1\s*>(?:(?!<(?:field|exclGroup)(?!\w)(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+>)[\S\s])*(?(DEFINE)(?<core>(?>(?><([\w:]+)(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+>)(?:(?&core)|)</\5\s*>|(?!</[\w:]+\s*>)(?>[\S\s]))+))
Replace VALUES (12345,"$3","/Tx", "", "N", "Y"),\r\n
https://regex101.com/r/icnF3i/1
Formatted (incase you need to look at it)
(?: # Prefix - Optional any chars that don't start a field or exclGroup tag
(?!
<
(?: field | exclGroup )
(?! \w )
(?>
" [\S\s]*? "
| ' [\S\s]*? '
| (?:
(?! /> )
[^>]
)?
)+
>
)
[\S\s]
)*
(?> # open 'field' or 'exclGroup' tag ------------------
<
( field | exclGroup ) # (1)
(?= # Asserttion (a pseudo atomic group)
(?: [^>"'] | " [^"]* " | ' [^']* ' )*?
\s name \s* = \s*
(?:
( ['"] ) # (2), Quote
( [\S\s]*? ) # (3), Name value - only thing we want
\2
)
)
\s+
(?>
" [\S\s]*? "
| ' [\S\s]*? '
| (?:
(?! /> )
[^>]
)?
)+
>
)
(?:
(?&core) # Call the core recursion function (balanced tags)
|
)
</ \1 \s* > # Close 'field' or 'exclGroup' tag ------------------
(?: # Postfix - Optional any chars that don't start a field or exclGroup tag
(?!
<
(?: field | exclGroup )
(?! \w )
(?>
" [\S\s]*? "
| ' [\S\s]*? '
| (?:
(?! /> )
[^>]
)?
)+
>
)
[\S\s]
)*
# ---------------------------------------------------------
(?(DEFINE)
(?<core> # (4 start), Inner balanced tags
(?>
(?>
<
( [\w:]+ ) # (5), Any open tag
(?>
" [\S\s]*? "
| ' [\S\s]*? '
| (?:
(?! /> )
[^>]
)?
)+
>
)
(?: # Recurse core
(?&core)
|
)
</ \5 \s* > # Balanced close tag (I can see you 5)
|
(?! </ [\w:]+ \s* > ) # Any char not starting a close tag (passive)
(?> [\S\s] )
)+
) # (4 end)
)
You can view the non-recursive version here https://regex101.com/r/ztOrP5/1
I am trying to simplify the RegEx provided in the previous answer.
This is my simplified version:
RegEx: (?|(?><field.*name\s*=\s*"([a-z_]\w*)"(?:.|\n)*?(?:<\/field>))|(?:<exclGroup.*name\s*=\s*"([a-z_]\w*)"(?:.|\n)*?(?:<\/exclGroup>)))
Replace: $1
Check it out over here: https://regex101.com/r/icnF3i/3
Appreciate your feedback.
Thanks to sln for helping me to reach this level.
EDIT:
The above RegEx doesn't work in Notepad++.
To use the same under Notepad++ use the following find/replace combination:
Find: (?i)<(field|exclGroup).*name\s*=\s*"([a-z_]\w*)"[\s\S]*?<\/\1>
Replace: \(12345,"$2","/Tx", "", "N", "Y"\),
I have the following template:
{{if . eq "login failed"}}
<span class="text-error">Incorrect username or password</span>
{{else if . eq "login success"}}
<span class="text-success">You have successfully logged in!</span>
{{end}}
I am passing a string when I execute the template.
However, I get the following error:
executing "login.html" at <.>: can't give argument to non-function .
How do I compare the strings within the template?
eq is function, not an operator. It is called with the form: eq <x> <y> (not <x> eq <y>).
You can fix your template by moving the operands from the the sides of eq to after it:
{{if eq . "login failed"}}
<span class="text-error">Incorrect username or password</span>
{{else if eq . "login success"}}
<span class="text-success">You have successfully logged in!</span>
{{end}}
To compare if two strings equal :
{{ if eq .Status "Approved" }}
...Do something
{{ else }}
...Do something else
{{ end }}
To compare if two strings not equal :
{{ if ne .Status "" }} // If status is not empty
...Do something
{{ else }}
...Do something else
{{ end }}
There are more golang HTML template directives here at : https://pkg.go.dev/text/template#hdr-Actions
I've got customUIXml object of type XDocument and it has the following XML as value:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<ribbon>
<tabs>
<tab id="t1" label="Shalala">
<!-- stuff -->
</tab>
<tab id="tab_dev" label="SomeOtherTab">
<!-- stuff -->
</tab>
<tab id="t108" label="MyTab">
<!-- stuff -->
</tab>
</tabs>
</ribbon>
</customUI>
and I want to get the tab node with label value "MyTab". This is the code I use:
Dim xtab As XElement = Nothing
Dim nodes = From nodeToTake In customUIXml.Descendants().Elements("tab") _
Where nodeToTake.Attribute("label").Value = "MyTab"
Select nodeToTake
For Each tab As XElement In nodes
xtab = tab
Next
But I get no results and I can't seem to find what am I doing wrong...
You could simply use XML literals, so your code would be as easy as:
Dim xtab = customUIXml.<ribbon>.<tabs>.<tab>.First(Function(tab) tab.#label = "MyTab")
Also, your code seems to work, so your problem seems to be elsewhere.
Dim customUIXml = <customUI>
<ribbon>
<tabs>
<tab id="t1" label="Shalala">
<!-- stuff -->
</tab>
<tab id="tab_dev" label="SomeOtherTab">
<!-- stuff -->
</tab>
<tab id="t108" label="MyTab">
<!-- stuff -->
</tab>
</tabs>
</ribbon>
</customUI>
Dim xtab As XElement = Nothing
Dim nodes = From nodeToTake In customUIXml.Descendants().Elements("tab") _
Where nodeToTake.Attribute("label").Value = "MyTab"
Select nodeToTake
For Each tab As XElement In nodes
xtab = tab
Next
Console.WriteLine(xtab)
displays
<tab id="t108" label="MyTab">
<!-- stuff -->
</tab>
just fine.
If your actual XML contains a namespace, you have to take that into account:
...
Dim df As XNamespace = customUIXml.Name.Namespace
Dim xtab As XElement = Nothing
Dim nodes = From nodeToTake In customUIXml.Descendants().Elements(df + "tab") _
...
string xml = "<customUI xmlns='http://schemas.microsoft.com/office/2009/07/customui' onLoad='Ribbon_Load'><ribbon><tabs><tab id='t1' label='Shalala'><!-- stuff --></tab><tab id='tab_dev' label='SomeOtherTab'><!-- stuff --></tab><tab id='t108' label='MyTab'><!-- stuff --></tab></tabs></ribbon></customUI>";
var xelement = XElement.Parse(xml);
var list = xelement.Descendants().Where(x => x.Name.LocalName == "tab" && x.Attribute("label") != null).ToList();
list.ForEach(x => Console.WriteLine(x.Attribute("label").Value));
you can access localName to check the elment tag value ,
Checked with LinqPad and it works expectedly hope that helps..
:)
Edit : Vb code from Telerik convert :
Dim xml As String = "<customUI xmlns='http://schemas.microsoft.com/office/2009/07/customui' onLoad='Ribbon_Load'><ribbon><tabs><tab id='t1' label='Shalala'><!-- stuff --></tab><tab id='tab_dev' label='SomeOtherTab'><!-- stuff --></tab><tab id='t108' label='MyTab'><!-- stuff --></tab></tabs></ribbon></customUI>"
Dim xelement__1 = XElement.Parse(xml)
Dim list = xelement__1.Descendants().Where(Function(x) x.Name.LocalName = "tab" AndAlso x.Attribute("label") IsNot Nothing).ToList()
list.ForEach(Function(x) Console.WriteLine(x.Attribute("label").Value))
This question already has answers here:
How do you disable "Save and send" in Excel 2010 (in the File ribbon (called backstage in Office 2010)?
(3 answers)
Closed 8 years ago.
I try to rename my file myfile.xlsb to myfile.zip then open zip archive, create in them folder customUI, put in this folder file customUI.xml with data
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<backstage>
<tab idMso="TabShare" visible="false"/>
</backstage>
</customUI>
And then tried with data
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<officeMenu>
<menu idMso="FileSendMenu" enabled="false"/>
</officeMenu>
</ribbon>
</customUI>
and then
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<officeMenu>
<menu idMso="FileSendMenu">
<button idMso="FileSendAsAttachment" enabled="false"/>
<button idMso="FileEmailAsXpsEmailAttachment" enabled="false"/>
</menu>
</officeMenu>
</ribbon>
</customUI>
Then I put in .rels file
<Relationship Id="rId5"
Type="http://schemas.microsoft.com/office/2006/relationships/
ui/extensibility" Target="customUI/customUI.xml"/>
between required tags and change this file in zip archive.
Then I rename myfile.zip to myfile.xlsb and open it but all send button still alive.
Also I tried to change all reference (http://schemas.microsoft.com/office/2006/relationships/ by http://schemas.microsoft.com/office/2009/07/customui) but no effect
This one also do not hide this buttons.
Application.CommandBars("Worksheet Menu Bar").Controls("File").Controls("Send To").Enabled = False
Application.CommandBars("Worksheet Menu Bar").Controls("File").Controls("Save & Send").Enabled = False
I need to disable this one and control it from VBA.
Control Name: SendCopySendToMailRecipient ; FileEmailAsPdfEmailAttachment ; FileEmailAsXpsEmailAttachment ; SendUsingEmail ; GroupSendUsingEmail
Control Type: toggleButton ; button ; button ; task ; group
Tab Set: None (Not in the Ribbon) ; None (Not in the Ribbon) ; None (Not in the Ribbon) ; None (Backstage View) ; None (Backstage View)
Tab: None (Not in the Ribbon) ; None (Not in the Ribbon) ; None (Not in the Ribbon) ; TabShare ; TabShare
Group: - ; None (Not in the Ribbon) ; None (Not in the Ribbon) ; GroupShare ; GroupShare
Parent Control: - ; FileSendMenu ; FileSendMenu ; Share ; Share
Secondary Parent Control: - ; - ; - ; - ; SendUsingEmail
Policy ID: 3738 ; 15730 ; 15731 ; 18209 ; 18166
Ordering: 645 ; 1049 ; 1050 ; 2219 ; 2220
This hides almost everything - maybe helps:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon startFromScratch="true">
<qat>
<documentControls>
<control
idMso="WindowSwitchWindowsMenuExcel"
screentip="SWITCH EXCEL FILE"
supertip="Click here to switch from this workbook to another open excel file."/>
<control
idMso="FilePrint"
screentip="PRINT FILE"
supertip="Click here to enable the print menu."/>
</documentControls>
</qat>
</ribbon>
</customUI>