TAL attribute - if attribute variable is nothing then put "this" instead - template-engine

I am having a hard time with an optional tal attribute.
<tal:block define="y_width options/youtube_width | nothing;">
<div width="437" tal:attributes="width y_width | string:600;"></div>
</tal:block>
I want to keep it so that if the user doesn't enter any options in the width value it will default to 437. I thought I could change the "or nothing" operator in the define block but that doesn't work. Above is another thing I tried out putting the or after the attribute but in either case the code justs go away. How can I make it so that if the user input values are empty, the code defaults to certain values?

You'll have to use a python expression here, as the | pipe operator only kicks in on AttributeError or KeyError, but in your case "y_width" will be None:
<tal:block define="y_width options/youtube_width | nothing;">
<div width="437" tal:attributes="width python:y_width or 600;" ></div>
</tal:block>

Related

Is it possible in XPATH to find an element by attribute value, not by name?

For example I have an XML element:
<input id="optSmsCode" type="tel" name="otp" placeholder="SMS-code">
Suppose I know that somewhere there must be an attribute with otp value, but I don’t know in what attribute it can be, respectively, is it possible to have an XPath expression of type like this:
.//input[(contains(*, "otp")) or (contains(*, "ode"))]
Try it like this and see if it works:
one = '//input/#*[(contains(.,"otp") or contains(.,"ode"))]/..'
print(driver.find_elements_by_xpath(one))
Edit:
The contains() function has a required cardinality of first argument of either one or zero. In plain(ish) English, it means you can check only one element at a time to see if it contains the target string.
So, the expression above goes through each attribute of input separately (/#*), checks if the attribute value of that specific attribute contains within it the target string and - if target is found - goes up to the parent of that attribute (/..) which, in the case of an attribute, is the node itself (input).
This XPath expression selects all <input> elements that have some attribute, whose string value contains "otp" or "ode". Notice that there is no need to "go up to the parent ..."
//input[#*[contains(., 'otp') or contains(., 'ode')]]
If we know that "otp" or "ode" must be the whole value of the attribute (not just a substring of the value), then this expression is stricter and more efficient to evaluate:
//input[#*[. ='otp' or . = 'ode']]
In this latter case ("otp" or "ode" are the whole value of the attribute), if we have to compare against many values then an XPath expression of the above form will quickly become too long. There is a way to simplify such long expression and do just a single comparison:
//input[#*[contains('|s1|s2|s3|s4|s5|', concat('|', ., '|'))]]
The above expression selects all input elements in the document, that have at least one attribute whose value is one of the strings "s1", "s2", "s3", "s4" or "s5".

Show default content in a template if an object is nil otherwise show based on the set property

In my template, I would like to include some default meta tags (90% of the time). However, when a specific property is set, I would like to show a different set of text.
I know I can set an anonymous struct and set a property with either "default" or "some-x". However, this means, I need to add an anonymous struct to 90% of my handlers that just currently pass nil.
Is there way to do something like
{{if eq . nil}}
// default meta tag
{{else if eq .MetaValue "some-x"}}
//other
{{end}}
If I try something like my above code, it compiles but doesn't do what I want. Appreciate any suggestions on how to handle it properly without adding a lot of boiler plate.
Thanks!
{{if not .}}
output when . is nil or otherwise empty including
false, 0, and any array, slice, map, or string of length zero
{{else if eq .MetaValue "some-x"}}
// some-x case
{{else}}
// other case
{{end}}
If you want to ensure you're only checking against nil and not 0, false, the empty string, or any other falsey type, you can use the kindIs function to accomplish this.
{{ if kindIs "invalid" . }}
// only if variable is literally nil. falsey values will fallthrough.
{{ else if eq .MetaValue "some-x" }}
// other
{{ else }}
// final case, if any
{{ end }}
I've been recently facing an issue with identifying nil vs 0 values in a Helm Chart (which uses Go templates, including sprig) and haven't found any solutions posted, so I thought I'd add mine here.
I came up with a kind of ugly solution which is to quote the value and then check for a string that matches "<nil>" (with quotes, so you'd actually be checking (quote .Values.thing | eq "\"<nil>\"")). This allows differentiating tests against empty values vs defined 0 values. In my case, I was trying to build a config file where some default options were non-0, so when 0 was explicitly set, I wanted to know that 0 was set instead of just omitted.
Hopefully this can be a help to someone else.
It would be nice to have a better way to do this, but so far I haven't found anything that doesn't require creating and adding my own template functions.

Check if the node value exist

I want to check in a xml if there is a node with the value "Hotel Hafen Hamburg".
But I get the error.
SimpleXMLElement::xpath(): Invalid predicate on line 25
You can view the xml here.
http://de.sourcepod.com/dkdtrb22-19748
Until now I have written the following code.
$apiUmgebungUrl = "xml.xml";
$xml_umgebung = simplexml_load_file($apiUmgebungUrl);
echo $nameexist = $xml_umgebung->xpath('boolean(//result/name[#Hotel Hafen Hamburg');
It seems that your parantheses and brackets do not close properly at the end of your XPath expression - it should end on ]).
Also, what is Hotel Hafen Hamburg? If it is an attribute called value, your value check should look like this:
[#value="Hotel Hafen Hamburg"]
You cannot just write # and then a value, without specifying where that value is supposed to be.
EDIT: Looking at the Xml document, it seems that Hotel Hafen Hamburg is supposed to be the text content of the <name> element. Therefore, try looking for a text node with that value rather than an attribute:
boolean(//result/name[text() = "Hotel Hafen Hamburg"])

jxls forEach tag : how to define local variables?

Can we define local variables in jxls which can be used to set an incrementing count for a column.
For eg: Consider the following
<jx:forEach items="${myList}" var="myVar">
-- i need to define a local integer variable here which will have an initial value as 0
-- and i will increment it and display in the output xls's first column
</jx:forEach>
Basically my requirement is to have somekind of local variable declaration in jxls code which i would increment and display in xml.
Any other alternatives are welcome.
Regards,
Rahul
jx:forEach tag support varStatus attribute which defines a name of loop status object which will be passed into bean context for each iteration. The loop status object is an instance of LoopStatus class which has single 'index' property identifying the index of the current item in the collection being iterated
<jx:forEach items="${employees}" var="employee" varStatus="status">
| ${status.index} | ${employee.name} | ${employee.payment} | ${employee.bonus}
</jx:forEach>
Figured it out.... We can use <jx:out expr="hssfRow.getRowNum()" /> in the column where we want to display the numbering. We can keep the above piece of code inside <jx:forEach items="${myList}" var="myVar"> tag

Is there a DRYer XPath expression for union?

This works nicely for finding button-like HTML elements, (purposely simplified):
//button[text()='Buy']
| //input[#type='submit' and #value='Buy']
| //a/img[#title='Buy']
Now I need to constrain this to a context. For example, the Buy button that appears inside a labeled box:
//legend[text()='Flubber']
And this works, (.. gets us to the containing fieldset):
//legend[text()='Flubber']/..//button[text()='Buy']
| //legend[text()='Flubber']/..//input[#type='submit' and #value='Buy']
| //legend[text()='Flubber']/..//a/img[#title='Buy']
But is there any way to simplify this? Sadly, this sort of thing doesn't work:
//legend[text()='Flubber']/..//(
button[text()='Buy']
| input[#type='submit' and #value='Buy']
| a/img[#title='Buy'])
(Note that this is for XPath within the browser, so XSLT solutions will not help.)
Combine multiple conditions in a single predicate:
//legend[text()='Flubber']/..//*[self::button[text()='Buy'] or
self::input[#type='submit' and #value='Buy'] or
self::img[#title='Buy'][parent::a]]
In English:
Select all descendants of the parent (or the parent itself)
for any legend element having the
text "Flubber" that are any of 1) a button
element having the text "Buy" or 2) an
input element having an attribute
type whose value is "submit" and an
attribute named value whose value is
"Buy" or 3) an img having an
attribute named title with a value
of "Buy" and whose parent is an a
element.
From comments:
Adjusting slightly to obtain the A
rather than the IMG:
self::a[img[#title='Buy']]. (Now if
only 'Buy' could be reduced
Use this XPath 1.0 expression:
//legend[text() = 'Flubber']/..
//*[
self::button/text()
| self::input[#type = 'submit']/#value
| self::a/img/#title
= 'Buy'
]
EDIT: I didn't see the parent accessor. Other way in one direction only:
//*[legend[text() = 'Flubber']]
//*[
self::button/text()
| self::input[#type = 'submit']/#value
| self::a/img/#title
= 'Buy'
]

Resources