XPATH select random number of nodes AND have multiple conditions - xpath

I need to select a random number of product details from XML and have multiple conditions.
The below selects 8 products, but they are not random - how to make this random?
$randomProducts = $prod_xml->xpath("/products/product[position()<
9]");
The below makes a selection on multiple conditions.
$featuredProducts = $prod_xml->xpath('/products/product[featured =1
and hidden !=1]');
How do I combine the two to get random featured products that are not set to hidden?

Depending on whether you want first to get all non-hidden and featured products an then select 8 of them, or get 8 products and then select all of them that are featured and non-hidden, you will have two different XPath expressions:
/products/product[featured =1 and hidden !=1][position() < 9]
and correspondingly:
/products/product[position() < 9][featured =1 and hidden !=1]
Now, the "random" part ...
Neither XPath 1.0 nor XPath 2.0 (or even the W3C working drafts for XPath 3.0 and its standard functions) have a function that returns a pseudo-random sequence of integers (or of anything).
Therefore, you have to form this sequence of eight pseudorandoms and generate an XPath expression as this:
/products/product[featured =1 and hidden !=1]
[contains('|3|5|12|19|4|23|11|7|', concat('|',position(),'|)) ]

Related

How to make Tableau run query for combined multiple selections in quick filter, example attached

It is hard to describe my question in the subject line. Here is an example.
I want Tableau to run query to show only Account ID that has both 2 products i selected in Product A quick filter.In this example only the second Account ID should qualify . Is this possible?
Thanks for your help in advance!
Hmm, good question. It is not possible in the way you want (at least I can't think of a way to do that), with quick filters.
I can solve your specific problem (filtering customers that have at least 2 specific products in their history), but expanding for variable n products can be really troublesome.
So first thing, create 2 parameters. Product1 and Product2. Each is a string, and you can get a list from the [Product A] field. You will use this 2 parameters to specify the 2 products you want.
Now create a calculated field, [Product flag]:
IF [Product A] = [Product1] OR [Product A] = [Product2]
THEN 1
END
Now drag [Account ID] to the filters shelf. Open the filter options and go to condition. Now select By field, [Product flag], Sum, = 2
That will work if there are not duplicated [Product A] under the same [Account ID]. If that can happen, you need a little bit more sophisticated approach. [Product Flag] becomes:
IF [Product A] = [Product1]
THEN 1
ELSEIF [Product A] = [Product2]
THEN 2
END
And the condition should be Count (Distinct) = 2
In both cases it will keep only the Account IDs that have both the products you selected under them. They can have other products under them.
EDIT: For the N product problem, I believe you're going to use a solution outside Tableau. One possibility is to use the JS API, so you can select the products you need in a JS interface, and pass a parameter to Tableau.
In JS you could have a list you could select as many items you want, and a script to pass a parameter to Tableau based on the selection. Could be something like: product1,product2,product3...
Then you could use CONTAINS() to see if that product is in that list (and raise a flag), and make a count of ',' to see how many products were selected.
Unfortunately I have very limited knowledge on JS API, but I strong encourage you to take a look
Really interesting question. It's surprisingly trickier to list the accounts that reference every product in a list than it is to list the accounts that reference any product in a list.
If you are willing to start with a less convenient user interface (suitable for ad-hoc analysis but not published dashboards) then try the following:
Create a filter based on Account Id, select Use all on the General tab, and By formula on the Condition tab. Enter the formula
Count(if [Product A] = "Business Office Consolidation" then 1 end) > 0 and Count(if [Product A] = "Cabled Barcode Scanner" then 1 end) > 0
This will only filter to only include Account IDs that reference both products. You can extend this to a list of any number of required products. For relational data sources, it is implemented using a HAVING clause.
Of course, it can be tedious to revise this formula by hand, but it is one way to accomplish your analysis goal, and it can be instructive to understand how filter conditions work. Similar formulas are useful for many conditions.
You can create one or more dynamic sets using the same approach and then use them in calculated fields, any shelf in Tableau and combine them to create new sets. You can also move the formula to a calculated field for convenience.
Note, the 1 in the formula is not significant, any non-null value would work. Since there is no else clause, the formula evaluates to null for rows that fail the if test. And the Count() function just counts the number of rows that have non-null values for the expression.
To come up with an approach that lets you easily select products from a list without editing a formula, will probably take some combination of more advanced features. I don't have an answer for you right now, but the features that are worth learning about that may or may not be part of the solution include filter actions, context filters, top filters, count distinct, custom SQL, computed sets, table calculations, LOD expressions and the Javascript API. This would also be a good questions to pose, with an example workbook, on the Tableau online forums at http://www.tableau.com under the Support menu.

Easiest way to scope / filter string Ruby data with range slider

I have a light search engine I'm trying to build out. One of the search requirements is a slider range, 0-10 based on a persons experience.
In the User attribute experience we store 5 strings (0-1, 2-3, 4-5, 6-8, 10+)
I've been using ruby scopes in the model for the other attributes, but what is a good solution for filtering on a range of string data like this?
So for example if the end user selects the slider from 1-8, it would display all user records that have this attribute marked with (0-1, 2-3, 4-5, 6-8) and not render any users with 10+
Convert the strings to actual numbers and store the actual numbers in the db instead of (or even as well as) strings.
In this case: (0-1, 2-3, 4-5, 6-8, 10+) maps nicely onto the numbers 1-5
Then you can use > < in SQL quite easily.
eg slider '1-8' converts to SQL of the_column >= 0 AND the_column <= 4

Random product selection using Jmeter

I have to performance test an e-commerce web-application using Jmeter.
One flow is like Search > select any product > Add to Cart.
Here I have to select any random product from the search results and proceed.
Can you please guide me on how to select any random product and proceed?
I am using Jmeter 2.11.
You can follow below sequence,
(If you know how many products are there then)
1. add random variable with values 1-no. of products. this will generate random values for each user/iteration
2. use values from random variable (var1) in regular expression extractor for random occurance (var1 occurance which is random every time)
(If you dont know how many products are present and if your response contains no. of products count then)
1. In first regular expression extract count of products in a variable
2. add random variable with values 1-value for first regex. this will generate random values for each user/iteration
3. use values from random variable (var1) in regular expression extractor for random occurance
I have used similar technique in my assgn. attaching snapshots for reference.
Random selector
first regex for count
random variable
2nd regex for random oocurance
you can modify regex as per your requirement.

xpath - get count of rows based on some text

I'm writing xpaths to select all the links under each category on left sidebar from following page:
http://www.indexmundi.com/commodities/'>http://www.indexmundi.com/commodities/
I want to select the link under each category one by one. I've written the following xpath and it is selecting the link under first category(Commodity Price Indices) somehow. But I was wondering how I will select the links under other categories. I want to add a check on h3 tha if it's text is Energy, count and select all the rows before that, then if h3 text is Beverages, count and select all rows between Energy and Beverages
.//*[#id='dlCommodities']/tbody/tr[position()< count(following-sibling::tr/td/h3)-1]/td/a
Here is another xpath:
.//*[#id='dlCommodities']/tbody/tr[preceding-sibling::tr/td/h3[. = 'Energy'] and following-sibling::tr/td/h3[. = 'Beverages']]/td/a
It is fulfilling the second requirement i.e. select rows between specific headings but it is missing one node.
Please help me fix these xpaths or suggest a better one.
Thanks
I understand your actual problem as: Find all links that belong to a given category. For doing so, find the category, and then retrieve all elements before the next category.
You might remove the newlines if you prefer, I added them for readability.
//tr[td/h3="Energy"]/(self::tr, following-sibling::tr[
. << //tr[td/h3="Energy"]/following-sibling::tr[td/h3][1]
])
If you do not have an XPath 2.0 compatible processor, you cannot use the << operator which test for node order (the current node must precede the next category). An XPath 1.0 solution is even slightly shorter, but in my opinion worse in readability:
//tr[td/h3="Energy"] | //tr[td/h3="Energy"]/following-sibling::tr[
./preceding-sibling::tr[td/h3][1][td/h3="Energy"] and not(td/h3)
]
Both queries will select all nodes of a category; to count them wrap them into count(...).

Call subreport multiple times and pass value from array

I have a Main Report and three Subreports (they have different sizes).
I have an array which gives the order in which those three reports should run (003, 001, 002 for example - meaning report 3 will run first, then 1, then 2).
Is it possible to have one placeholder for a subreport that loops through the array (3 times in this case only) and then adjusts the size of the subreport it calls (also adjusting the path based on array value in the subreport expression of course)?
If you can use DB connection in a sub-report, you can construct SQL query from the array, some thing like:
select '003' as rep_order
union all
select '001' as rep_order
union all
select '002' as rep_order
and pass it to a sub report to use it as a query. In query editor for sub report write something like:
$P!{ARRAY_QUERY}
Then in this sub-report add a sub-report element in a details band. For the above query it will run 3 times...
If you are going to generate query in a report you cant loop thru array so you'll have to hard-code number of array elements...

Resources