Looking for a way to go to a few websites (10 sites) and grab a set of data, need a proper way to do since I am new to coding.
code:
WebUI.openBrowser('');
WebUI.navigateToUrl("www.site1.com");
WebUI.maximizeWindow();
String text1 = WebUI.getText(findTestObject("xpath"));
Do I need to do this for all the 10 websites?
Let's say you have the 10 URLs in an array. Create another empty array that will hold the text values:
WebUI.openBrowser('');
def mySites = ["www.site1.com", "www.site2.com", "www.site3.com", "www.site4.com", "www.site5.com", "www.site6.com", "www.site7.com", "www.site8.com", "www.site9.com", "www.site10.com"];
def myTexts = [];
Then loop your above code in a for loop, and add the text values to the array (note: xpath element name is the same for all the sites in this example, you should edit that according to your needs):
for(i=0; i<mySites.size; i++){
WebUI.navigateToUrl("www.site1.com");
WebUI.maximizeWindow();
myTexts << WebUI.getText(findTestObject("xpath"));
}
Related
I managed to create an own inline content element (on tt_content table) but when i try to get the values on the frontend via fluid, i get nothing.
I debugged the {data} variable and on the column that my data are saved, there is an integer. I suppose it reads the number of the content elements which were created on the foreign table (accordion). How can i get those values?
At this point the {data} variables reads the tt_content table and the column that has the integer reads the number of content elements on the table accordion.
I suppose no code is necessary. If it is necessary, feel free to comment the part of the code you would like to review.
Best regards
You need to add a DataProcessor to your TypoScript creating the content element, which fetch your accordion records. Example:
tt_content {
yourContentElementName < lib.contentElement
yourContentElementName.templateName = YourContentElementName
yourContentElementName.dataProcessing {
10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
10 {
if.isTrue.field = fieldInTtContentWithInteger
table = your_accordion_table
pidInList = this
where.field = uid
where.intval = 1
where.dataWrap = field_pointing_to_ttcontent_record = |
as = accordions
}
}
}
I am new to apache velocity, I want to create a subList Object from the List Objects which are coming from some service call in .vm file.
We need to render the list based on some logic in parts, for that we want to create sublist from list.
$table.getBooks() //contains all the Books objects
Below is the sample code which I tried but it did not work.
#set($segregatedList = [])
#set($size = $table.getLineItems().size())
#foreach($index in [0..$size-1])
#set($value = $index + 4)
#set($minimum = $math.min($nItems,$value))
$segregatedList.add($table.getBooks().subList($index,$minimum)))
$index += 4
#end
I executed the code, while rendering $segregatedList is coming as null.
I verified $table.getBooks() contains the Objects as when I am passing this,Objects are getting rendered successfully.
Can someone please tell what I am doing wrong or how can I create a sublist ?
First you are increment index with 4 and can cause an IndexOutOfBoundsException, so need to change until size-5 (and therefore remove math minimum check)
Second you are adding single Element instead of all Elements using addAll
Third your size check if on wrong parameter - should be on relevant $table.getBooks()
And last make sure your list have more than 5 elements
#set($segregatedList = [])
#set($size = $table.getBooks().size())
#foreach($index in [0..$size-5])
#set($value = $index + 4)
$segregatedList.addAll($table.getBooks().subList($index, $value)))
$index += 4
#end
I have this response in soapUI:
<pointsCriteria>
<calculatorLabel>Have you registered for inContact, signed up for marketing news from FNB/RMB Private Bank, updated your contact details and chosen to receive your statements</calculatorLabel>
<description>Be registered for inContact, allow us to communicate with you (i.e. update your marketing consent to 'Yes'), receive your statements via email and keep your contact information up to date</description>
<grades>
<points>0</points>
<value>No</value>
</grades>
<grades>
<points>1000</points>
<value>Yes</value>
</grades>
<label>Marketing consent given and Online Contact details updated in last 12 months</label>
<name>c21_mrktng_cnsnt_cntct_cmb_point</name>
</pointsCriteria>
There are many many many pointsCriteria and I use the below xquery to give me the DB value and Range of what that field is meant to be:
<return>
{
for $x in //pointsCriteria
return <DBRange>
<db>{data($x/name/text())}</db>
<points>{data($x//points/text())}</points>
</DBRange>
}
</return>
And i get the below response
<return><DBRange><db>c21_mrktng_cnsnt_cntct_cmb_point</db><points>0 1000</points></DBRange>
That last bit sits in a property transfer. I need SQL to bring back all rows where that DB field is not in that points range (field can only be 0 or 1000 in this case), my problem is I dont know how to loop through each DBRange/DBrange in this manner? please help
I'm not sure that I really understand your question, however I think that you want to make queries in your DB using specific table with a column name defined in your <db> field of your xml, and using as values the values defined in <points> field of the same xml.
So you can try using a groovy TestStep, first parse your Xml and get back your column name, and your points. To iterate over points if the values are separated with a blank space you can make a split(" ") to get a list and then use each() to iterate over the points on this list. Then using groovy.sql.Sql you can perform the queries in your DB.
Only one more thing, you need to put the JDBC drivers for your vendor DB in $SOAPUI_HOME/bin/ext and then restart SOAPUI in order that it can load the necessary driver classes.
So the follow code approach can achieve your goal:
import groovy.sql.Sql
import groovy.util.XmlSlurper
// soapui groovy testStep requires that first register your
// db vendor drivers, as example I use oracle drivers...
com.eviware.soapui.support.GroovyUtils.registerJdbcDriver( "oracle.jdbc.driver.OracleDriver")
// connection properties db (example for oracle data base)
def db = [
url : 'jdbc:oracle:thin:#db_host:d_bport/db_name',
username : 'yourUser',
password : '********',
driver : 'oracle.jdbc.driver.OracleDriver'
]
// create the db instance
def sql = Sql.newInstance("${db.url}", "${db.username}", "${db.password}","${db.driver}")
def result = '''<return>
<DBRange>
<db>c21_mrktng_cnsnt_cntct_cmb_point</db>
<points>0 1000</points>
</DBRange>
</return>'''
def resXml = new XmlSlurper().parseText(result)
// get the field
def field = resXml.DBRange.db.text()
// get the points
def points = resXml.DBRange.points.text()
// points are separated by blank space,
// so split to get an array with the points
def pointList = points.split(" ")
// for each point make your query
pointList.each {
def sqlResult = sql.rows "select * from your_table where ${field} = ?",[it]
log.info sqlResult
}
sql.close();
Hope this helps,
Thanks again for your help #albciff, I had to add this into a multidimensional array (I renamed field to column and result is a large return from the Xquery above)
def resXml = new XmlSlurper().parseText(result)
//get the columns and points ranges
def Column = resXml.DBRange.db*.text()
def Points = resXml.DBRange.points*.text()
//sorting it all out into a multidimensional array (index per index)
count = 0
bigList = Column.collect
{
[it, Points[count++]]
}
//iterating through the array
bigList.each
{//creating two smaller lists and making it readable for sql part later
def column = it[0]
def points = it[1]
//further splitting the points to test each
pointList = points.split(" ")
pointList.each
{//test each points range per column
def sqlResult = sql.rows "select * from my_table where ${column} <> ",[it]
log.info sqlResult
}
}
sql.close();
return;
I have a PDF document that has several hundred fields. All of the field names have periods in them, such as "page1.line1.something"
I want to remove these periods and replace them with either an underscore or (better) nothing at all
There appears to be a bug in the itextsharp libraries where the renamefield method does not work if the field has a period, so the following does not work (always returns false)
Dim formfields As AcroFields = stamper.AcroFields
Dim renametest As Boolean
renametest = formfields.RenameField("page1.line1.something", "page1_line1_something")
If the field does not have a period in it, it works fine.
Has anyone come across this and is there a workaround?
Is this an AcroForm form or a LiveCycle Designer (xfa) form?
If it's XFA (which is likely given the field names), iText can't help you. It can only get/set field values when working with XFA.
Okay, an AcroForm. Rather than go the route used in your source, I suggest you directly manipulate the existing field dictionaries and the acroForm field list.
I'm a Java native when it comes to iText, so you'll have to do some translation, but here goes:
A) Delete the AcroForm's field array. Leave the calculation order alone if present (/CO). I think.
PdfDictionary acroDict = reader.getCatalog().getAsDictionary(PdfName.ACROFORM);
acroDict.remove(PdfName.FIELDS);
B) Attach all the 'top level' fields to a new FIELDS array.
PdfArray newFldArray = new PdfArray();
acroDict.put(newFldArray, PdfName.FIELDS);
// you could wipe this between pages to speed things up a bit
Set<PdfIndirectReference> radioFieldsAdded = new HashSet<PdfIndirectReference>();
int numPages = reader.getNumberOfPages();
for (int curPg = 1; curPg <= numPages; ++curPg) {
PdfDictionary curPageDict = reader.getPageN(curPg);
PdfArray annotArray = curPageDict.getAsArray(PdfName.ANNOTS);
if (annotArray == null)
continue;
for (int annotIdx = 0; annotIdx < annotArray.size(); ++annotIdx) {
PdfIndirectReference fieldReference = (PdfIndirectReference) annotArray.getAsIndirect(annotIdx);
PdfDictionary field = (PdfDictionary)PdfReader.getObject(fieldReference);
// if it's a radio button
if ((PdfFormField.FF_RADIO & field.getAsNumber(PdfName.FF).intValue()) != 0) {
fieldReference = field.get(pdfName.PARENT);
field = field.getAsDict(PdfName.PARENT); // looks up indirect reference for you.
// only add each radio field once.
if (radioFieldsAdded.contains(fieldReference)) {
continue;
} else {
radioFieldsAdded.add(fieldReference);
}
}
field.remove(PdfName.PARENT);
// you'll need to assemble the original field name manually and replace the bits
// you don't like. Parent.T + '.' child.T + '.' + ...
String newFieldName = SomeFunction(field);
field.put(PdfName.T, new PdfString( newFieldName ) );
// add the reference, not the dictionary
newFldArray.add(fieldReference)
}
}
C) Clean up
reader.removeUnusedObjects();
Disadvantage:
More Work.
Advantages:
Maintains all field types, attributes, appearances, and doesn't change the file as a whole all that much. Less CPU & memory.
Your existing code ignores field script, all the field flags (read only, hidden, required, multiline text, etc), lists/combos, radio buttons, and quite a few other odds and ends.
if you use periods in your field name, only the last part can be renamed, e.g. in page1.line1.something only "something" can be renamed. This is because the "page1" and "line1" are treated by adobe as parents to the "something" field
I needed to delete this hierarchy and replace it with a flattened structure
I did this by
creating a pdfdictionary object for each field
reading the annotations I needed for each field into an array
deleting the field hierarchy in my (pdfstamper) document
creating a new set of fields from my array data
I have created some sample code for this if you want to see how I did it.
Is there a way in Selenium RC to get the id from the xpath?
If I have the xpath
/html/body/div/div//input
I want to get the id of all the nodes associated to the xpath
You can use getAttribute in combination with getXpathCount.
A Selenium 1 example in Java would be:
int inputs = selenium.getXpathCount("/html/body/div/div/descendant::input").intValue();
for (int i=1; i<=inputs; i++) {
System.out.println(selenium.getAttribute("/html/body/div/div/descendant::input[" + i + "]#id"));
}
A Selenium 2 example in Java would be:
List<WebElement> inputs = driver.findElements(By.xpath("/html/body/div/div/descendant::input"));
for (WebElement input : inputs) {
System.out.println(input.getAttribute("id"));
}
You can get that by running a javascript, using this.browserbot.findElement('/html/body/div/div//input'):
Of course, this depends on the source language, but it would be something like this (in perl, untested):
#first count the number of inputs with ids
my $count = $selObj->get_xpath_count('/html/body/div/div//input[#id]');
#build a javascript that iterates through the inputs and saves their IDs
my $javascript;
$javascript .= 'var elements = [];';
$javascript .= "for (i=1;i<=$count;i++)";
$javascript .= " elements.push(this.browserbot.findElement('/html/body/div/div/input['+i+']').id);";
#the last thing it should do is output a string, which Selenium will return to you
$javascript .= "elements.join(',');";
my $idString = $selObj->get_eval($javascript);
I always thought there should be a more direct way to do this, but I haven't found it yet!
EDITED based on the comments, the for loop count should start from 1 and include $count, also the findElement line only needs one forward-slash before input.
EDIT2 Adding a completely different idea based on further comments:
Selenium's javascripts that get attached to every page include a function called eval_xpath that returns an array of DOM elements for a given query. Sounds like what you want?
Here's what I think the javascript would look like (again, untested):
var elements = eval_xpath('/html/body/div/div//input',this.browserbot.getCurrentWindow().document);
var results = [];
for (i=0;i<elements.length;i++){
results.push(elements[i].id);
}
results.join(',');