Simplexml get path from variable - variables

Is there a way to pass the path to a simplexml node as a variable?
This is what I tried:
//set the path to the node in a variable
$comp = 'component->structuredBody->component';
echo count($xml->component->structuredBody->component); //=== 13
echo count($xml->$comp); //===0
echo count($xml->{$comp});//===0

What you need is XPath, and more specifically SimpleXML's xpath() method. Instead of traversing using PHP's -> operator, you would traverse using XPath's / operator, but otherwise, could achieve exactly the effect you wanted:
$comp = 'component[1]/structuredBody[1]/component';
echo count( $xml->xpath($comp) );
You might think that this could be simplified to 'component/structuredBody/component', but that would find all possible paths matching the expression - that is if there are multiple structuredBody elements, it will search all of them. That might actually be useful, but it is not equivalent to $xml->component->structuredBody->component, which is actually shorthand for $xml->component[0]->structuredBody[0]->component.
A few things to note:
Unlike most operations with SimpleXML, the result is an array, not another SimpleXML object (think of it as a set of search results). It is therefore vital that you check it is not empty before accessing element 0 as an object.
As you can see in the example above, XPath counts from 1, not 0. I don't know why, but it's caught me out before, so I thought I'd warn you.
The library SimpleXML is built on supports only XPath 1.0;
examples you see online for XPath 2.0 may not work.
XPath 1.0 has no notion of a "default namespace", and SimpleXML doesn't automatically register namespace prefixes for use in XPath, so if you're working with namespaces, you need to use registerXPathNamespace().

Related

JMeter Compilable JSR223 Usage Precautions

Update - TL'DR:
When it comes to the compilable and cacheable JSR223 Elements, I've saw people using all sorts of tactics dancing around it. I had my doubts and I had my answers here, and found that most of tactics I saw are done wrong:
If your JSR223 scripts are full of args[0], args[1], args[2] everywhere, then that's the wrong choice of tactic, even it is the best practice of JMeter, it is not the best practice in the software engineering and easy-maintenance point of view.
Even if you assign args[n] to some meaningful-named variables, it is not the best practice in JMeter either, as there are much simpler and straightforward ways.
Similarly, if you are following the advices of "using vars.get("") to get variables" (then assign them to some meaningful-named variables), it is not the best practice in JMeter either, as there are much simpler and straightforward ways.
The advice of "Don't use ${} in JSR223 scripts" is more a myth than the truth, as all the ${} using examples in this question are just fine.
Also, the advices of breaking up expressions like "ValidAssetIds_${i+1}_g" with "+" into "ValidCatalogAssetIds_"+ (i+1) + "_g" is just another myth, and in most cases untruth, as illustrated in this question.
Now, as per JMeter's best practices for JSR223:
The reason JSR223 Elements is recommended for intensive load testing over Beanshell or Javascript, is because it implements the Compilable interface, as Groovy scripting engine implements Compilable.
And, it tells people to
ensure
to check (enable) the Cache compiled script if available property to ensure the script compilation is cached
the script does not use any variable using ${varName} as caching would take only first value of ${varName}. Instead use:
vars.get("varName"),
like:
Else, the other option is to pass them as Parameters to the script, like this:
Now, my question are,
What would happen if I use
def my_var = vars.get("MY_VARIABLE")
log.info("The value of my_var is ${my_var}")
in above example? Would log changes in each iteration when MY_VARIABLE changes?
Instead of above, I also tried to use
def my_var2 = __V(MY_VARIABLE)
def my_var3 = ${__V(MY_VARIABLE)}
but somehow I wasn't able to get the values of MY_VARIABLE. What I'm missing?
what if my ${varName} is dynamically defined, what would happen if I use ${varName} in such form? Like,
case 1:
for(def i = 0; i < validAssets.size(); i++) {
vars.put("ValidAssetIds_${i+1}_v","${i+1}")
}
case 2:
def varName = ${__time(/1000,)}
vars.put("MY_Log","abc${varName}")
Would each iteration have their own MY_Log values, or they all will be the same? I know I can guess my conclusion from observations, but the purpose of this question is to let me (or people) know the precautions when it comes to using JSR223 that we might not be aware of before. thanks.
All the "precautions" are described in the documentation
When using this feature, ensure your script code does not use JMeter variables or JMeter function calls directly in script code as caching would only cache first replacement. Instead use script parameters.
For example if you define a random string via User Parameters:
and try to refer it as ${randomString} in Groovy - it will be "random" only during the first iteration, on subsequent iterations the "first" value will be used:
Questions 1 and 3 are using Groovy's string interpolation feature, it's safe to use unless there is a clash with other JMeter Variables names
Question 2: you need to surround the __V() function with quotation marks otherwise the variable value is resolved but it's not defined in Groovy causing compilation error, you should see a message in jmeter.log file regarding it
def my_var2 = "${__V(MY_VARIABLE,)}"
Check out Apache Groovy: What Is Groovy Used For? article for more information on Groovy scripting in JMeter context.

How to identify an element by classname containing curly brackets

when i try to access element:
browser.element('.object{ media }');
I get the following error message:
Error: Argument was an invalid selector (e.g. XPath/CSS).
at element(".object{ media }") - index.js:312:3
Is it possible to access elements by class name including curly brackets?
As per your question and your code trials to access desired element with classname containing curly brackets i.e. {} you can use the following solution:
XPath:
"//*[#class=\"object{ media }\"]"
Following what #DebanjanB said,
You can use something called Regular Expressions to sort issues like this out, what Debanjan has shown you is known as this.
Regular Expressions Guide
It would be useful if you read through a guide so you fully understand the code you are putting into your project, this will allow you to make better use of it later on in your testing.
All the best,
Jack

Explanation of $ in Mule MEL

I cannot find any documentation around the use of $ in MEL other than a couple of lines here
You can refer to any Java class by its fully qualified name or if it
is one of the classes in the automatically-imported Java classes, by
its unqualified name. References use the same dot notation as in Java,
except that you must use $ rather than a dot to refer to a nested
class.
I can find a couple of examples here
JSON processing MEL has no direct support for JSON. The
json-to-object-transformer can turn a JSON payload into a hierarchy of
simple data structures that are easily parsed with MEL. For example,
the following uses a filtered projection to build the equivalent of
the
$..[?
(#.title=='Moby Dick')].price JSON path expression:
<json:json-to-object-transformer returnClass="java.lang.Object" />
<expression-transformer
expression="#[($.price in message.payload if $.title == 'Moby Dick')[0]]" />
I want to understand in which cases does the $ get used...
$ comes from MVEL, the language underlying MEL.
$ serves as the placeholder for the element being filtered. It is
actually a regular variable that exists inside the context of the
projection. You can also use it to return the current element in the
projection to the representative list.
Reference: http://mvel.codehaus.org/MVEL+2.0+Projections+and+Folds#MVEL2.0ProjectionsandFolds-Filters

Mule MEL usage difference

I have been using different forms of Mule's Expression language.
I couldn't figure out the difference between
#[flowVars.myVariable]
and
#[flowVars['myVariable']]
They both give the result when there is a variable. But why do they behave differently when the variable is not present?
Like if the variable being called is not available, then the first expression would result in a exception. Whereas the second expression just gives out a warning or prints out as is, if in a logger message.
Why is this difference?
Also when going through the documentation for Mule 3.6 I found that the second expression is not longer shown in the documentation.
Is the expression #[flowVars['myVariable']] being deprecated?
The difference comes from the way MVEL deals with these two different ways of accessing map entries.
#[flowVars['myVariable']] is equivalent to flowVars.get('myVariable'), which does not fail if the flowVars map does not contain the 'myVariable' entry,
#[flowVars.myVariable] treats the flowVars map as a virtual object, leading to an exception if the 'myVariable' entry is missing because in this case it doesn't resolve to a map get but instead to directly using an object member (either a field or a method), which must exist before being accessed.
I don't think #[flowVars['myVariable']] could be deprecated since it's a core feature provided by MVEL.
Reference: http://mvel.codehaus.org/MVEL+2.0+Property+Navigation#MVEL2.0PropertyNavigation-MapAccess
David has given a nice explanation around your question. To extend that explanation I would just like to add that you can use #[flowVars.?myVariable] to make your code null safe. This is equivalent to #[flowVars['myVariable']].
Regarding #[header:originalFilename], as David said this is not MEL. You can get a list of non-mel expressions which are commonly used in Mule applications in the following link.
http://www.mulesoft.org/documentation/display/current/Non-MEL+Expressions+Configuration+Reference

dojo.place how to pass parameter without surrounding HTML?

I'd like to do something like this:
dojo.place(this.message.subject, this.apSubject);
But it throw exception in Dojo 1.7 (I'm completely new to Dojo so I don't know if the same problem is under older versions)
To get it work I did:
dojo.place('<span>' + this.message.subject + '</span>', this.apSubject);
It looks like Dojo parse the first parameter of dojo.place and if there is no HTML it throw exception.
How to use it without spans?
Check the docs, In particular, the description of what the first argument receives:
dojo.place(node, refNode, pos)
node
Can be a String or a DOM node. If it is a string starting with “<”, it is assumed to be an HTML fragment, which will be created. Otherwise it is assumed to be an id of a DOM node.
Therefore, one things you can do is create a text node with the text you want
dojo.place( document.createTextNode(this.message.subject), this.apSubject)
And another thing you could try would be setting the innerHTML instead of using dojo.place:
this.apSubject.innerHTML = this.message.subject;
BTW, In my humble opinion, dojo.place is normaly kind of annoying to use. However, since I am not often doing this kind of DOM manipulation, I don't really know what are the alternatives people prefer to use.