Hello i want to ask what exactly this Xpath does if we use.
I understand that it selects all b nodes that appear before the current node and that are not the same with current node.
//b[not(preceding::*=.)]
So if xml is like:
<a>
<b>English</b>
<b>German</b>
<b>Italian</b>
<b>Belarusian</b>
<b>Russian</b>
<b>Bulgarian</b>
<b>French</b>
<b>English</b>
</a>
Does this keep the last occurrence of the node or the first? this is what i do not get.
I was thinking that it should keep the last but using this xpath in FILTERXML function i gives the result of keeping the first occurrence so the result was
{"English";"German";"Italian";"Belarusian";"Russian";"Bulgarian";"French"}
Can someone explain?
This XPath,
//b[not(preceding::*=.)]
selects all b elements that do not have a preceding element with the same string value.
One might use this XPath to select only the first such elements, eliminating later "duplicates."
Notes:
To limit the scope to preceding b elements, use //b[not(preceding::b=.)].
To limit the scope to preceding b sibling elements, use //b[not(preceding-sibling::b=.)]
It means "select all b nodes for which there doesn't exist a preceding node equal to the reference node". Therefore, keeping the first and rejecting the last is the correct behaviour.
Related
This is my first StackOverflow question, so apologies if I am unclear.
Currently, my work uses an Excel tracking doc to log project info. The column info is like so:
CELL B1 (Project Number) =IF(B2=""," ",MID(B2,FIND("P2",B2),9))
CELL B2 (Project Name) Client / P2XXXXXXX / Name
Thus, the P2XXXXXXX gets pulled out of B2 and populated into B1.
However, management has recently switched systems, so now, some project numbers have the P2XXXXXXX format and others have a PRJ-XXXXX format.
So we need a formula the produces nothing if the cell is blank and EITHER the P2XXXXXXX number or PRJ-XXXXX number if the cell is not blank.
Is it possible? If any further details are needed, let me know. Thanks in advance!
Well, if the / is always there then this can work:
IF(B2="","",MID(B2,FIND("/",B2,1)+2,9))
assuming the name is always 9 characters.
String Between Two Same Characters
Maybe the next month your company will start using a different first letter or could add more numbers e.g. SPRXXXXXXXXXX. So you could solve this problem by extracting whatever is between those two slashes.
=IF(B2="","",TRIM(MID(B2,FIND("/",B2)+1,FIND("/",B2,FIND("/",B2)+1)-FIND("/",B2)-1)))
Find the first character =FIND("/",B2), but we need the next one:
=FIND("/",B2)+1
Find the second character but search from the postition after the first found:
=FIND("/",B2,FIND("/",B2)+1)
Now get the string between them:
=MID(B2,FIND("/",B2)+1,FIND("/",B2,FIND("/",B2)+1)-FIND("/",B2)-1)
(note how the last minus was 'converted' from a plus to a minus (- + + = -)).
Remove the leading and trailing spaces:
=TRIM(MID(B2,FIND("/",B2)+1,FIND("/",B2,FIND("/",B2)+1)-FIND("/",B2)-1))
Add the condition when the cell is blank:
=IF(B2="","",TRIM(MID(B2,FIND("/",B2)+1,FIND("/",B2,FIND("/",B2)+1)-FIND("/",B2)-1)))
Here's another way using LEFT and RIGHT:
=IF(B2="","",TRIM(LEFT(RIGHT(B2,LEN(B2)-FIND("/",B2)),FIND("/",B2))))
Although you can solve this problem with a combination of slicing, trimming, and complex conditionals, the most expressive and easy to maintain solution is to use regular expressions. Regular expressions have a bit of a learning curve, but there's a great playground website where you can experiment with them, and this page has a pretty good writeup on how regular expressions work in excel.
Specifically, this regular expression addresses the two naming conventions you've highlighted, but it can be updated to support more naming conventions as your company inevitably adds more:
P(RJ-)?((\d){9}|(\d){5})
To break that down from left to right:
P: both patterns start with a "P"
(RJ-)? One pattern follows with "RJ-", but the other doesn't. This is a grouped part of the pattern, and the question mark means that this part of the pattern is optional.
((\d){9}|(\d){5}): by far the nastiest part, but this basically means that there is going to be a sequence of numbers (\d), and there will either be nine of them or five of them. By wrapping the whole thing in parenthesis, they are always the second captured group, no matter the length of the sequence of numbers. This means that you can always extract the project id by looking at the value of the second capture group.
You can also make the expression more generalized by replacing ((\d){9}|(\d){5}) with simply (\d+). That just means "one or more digits." That gives you a much more simplified overall expression of this:
P(RJ-)?(\d+)
Depending on whether or not you care about validating strictly that project ids are 5 OR 9 digits long, that pattern above might be suitable, and it has the benefit of being more flexible. Still, the project ID is in the second captured group.
I want to tell python that everything before a certain character in a string, equals something else. In this code, I want everything after the equals sign to be assigned to a separate list called results, and everything before the equals sign to be assigned to a whole other list called names.
I believe an if/else statement is needed, but I do not know how to signify BEFORE and AFTER in python.
lines = ['Data1 = 100',
'Data2 = TRUE',
'Data3 = 45',
'Data4 = False',
]
You could make use of the list() function. Which splits the string into characters. Your problem with this is that you'll have to either specify the position on number of time the character appears before hand in order to get a start and stop location.
Another option is using the str.replace() if you know exactly what you want to replace, but both of these method present the problem that they are hard coded. If you're only wanting to replace them within a conditional statement, these could be useful.
For your use, you could say something like
loop through array.
split the element in the array using split
add logic statement that if array[i-1] == "=", start replacing elements with new element
then add the new element back into the array at the position you removed wanted to be removed.
I have this string to match some text using VLOOKUP.
=CONCATENATE(VLOOKUP(D10,Clients!A1:F10034,2),", ",VLOOKUP(D10,Clients!A1:F30034,3),", ",VLOOKUP(D10,Clients!A1:F10034,4),", ",VLOOKUP(D10,Clients!A1:F10034,5))
When it runs into a match that has a full stop in it, the match returns the first result that matches what it has before the full stop.
Eg if the lookup tries to match "C.B.A Solutions" and there is "C Tyres" & "C.B.A Solutions" inside of "Clients!" it will match "C Tyres" because it comes up first.
Your VLOOKUPS are missing the 'optional' forth argument. Note that this forth argument isn't 'optional' unless your data is sorted in ascending order and a match is guaranteed (i.e. your lookup term will always exist in the lookup database). Is that the case here? If so, amend your question to clarify. If not, add 'False' in as a forth argument.
Note that your formula is very inefficient. Most of the work that VLOOKUP does is in locating a matching row in the key column where the lookup term is. Better to relegate that computationally expensive task to a dedicated MATCH function in its own column, and then to feed that result to four INDEX functions.
Put this in a separate column:
=MATCH(D10,Clients!A1:F10034,0)
Then point some INDEX functions at the answer, instead of using computationally expensive VLOOKUP functions:
=CONCATENATE(INDEX(Clients!C1:C30034,[Match Output]),", ",INDEX(Clients!D1:D30034,[Match Output]),,", ",INDEX(Clients!E1:E30034,[Match Output]),)
Replace [Match Output] with the cell containing the output of the MATCH function.
Google INDEX and MATCH vs VLOOKUP for why this matters.
Note that sorting your lookup lists and then ommittig that forth argument and using something called the Double VLOOKUP trick (that handles missing values in your lookup list) will be many thousands of times faster again. See my post at the following link for more:
http://dailydoseofexcel.com/archives/2015/04/23/how-much-faster-is-the-double-vlookup-trick/
I want to insert an element into a list in a specific position. I don't want to replace the previous element but rather push everything forward. Is there a way to do this natively in the cassandra or must I take the list out and rewrite it?
thank you.
from the datastax documentation:
Add an element at a particular position using the list index position in square brackets
UPDATE users SET top_places[2] = 'riddermark' WHERE user_id = 'frodo';
When you add an element at a particular position, Cassandra reads the entire list, and then writes only the updated element. Consequently, adding an element at a particular position results in greater latency than appending or prefixing an element to a list.
I don't want to replace the previous element but rather push everything forward
You can't do that, you need to read and rewrite the entire list
Seems like it would be a simple thing really (and it may be), but I'm trying to take the string data of a column and then through a calculated column, replace all the spaces with %20's so that the HTML link in the workflow produced email will actually not break off at the first space.
For example, we have this in our source column:
file:///Z:/data/This is our report.rpt
And would like to end up with this in the calculated column:
file:///Z:/data/This%20is%20our%20report.rpt
Already used the REPLACE, and made up a ghastly super nested REPLACE/SEARCH version, but the problem there is that you have to nest for EACH potential space, and if you don't know how many up front, it doesn't work, or will miss some.
Have any of you come across this scenario and how did you handle it?
Thanks in advance!
As far as I know there is no generic solution using the calculated-column syntax. The standard solution for this situation is using an ItemAdded (/ItemUpdated) event and initializing the field value from code.
I was able to solve this issue for my circumstances by using a series of calculated columns.
In the first calculated column (C1) I entered a formula to remove the first space, something like this:
=IF(ISNUMBER(FIND(" ",[Title])),REPLACE([Title],FIND(" ",[Title]),1,"%20"),[Title])
In the second Calculated column (C2) I used:
=IF(ISNUMBER(FIND(" ",[C1])),REPLACE([C1],FIND(" ",[C1]),1,"%20"),[C1]).
In my case, I wanted to encode upto four spaces, so I used 3 calculated columns (C1, C2, C3) in the same fashion and got the desired result.
This is not as efficient as using a single calculated column, but if SUBSTITUTE will not work in your SharePoint environment, and you cannot use an event handler or workflow, it may offer a workable alternative.
I actually used a slightly different formula, but it was on a work machine to which I don't have access at the moment, so I just grabbed this formula from a similar S.O. question. Any formula that will replace the first occurrence of a space with "%20" will work, the trick is to a) make sure the formula returns the original string unchanged if it does not have more spaces in it, and b) test, test, test. Create a view of your list that has the field you are trying to encode, plus the calculated fields, and see if you are getting the results you want.
so that the HTML link in the workflow produced email will actually not break off at the first space.
The browser only does this if you have not enclosed your link in quotes
If you wrap the link in quotes, it does not cut off at the first space
In a SharePoint Formula it would be:
="""file:///Z:/data/This is our report.rpt"""
becuase two quotes are the SP escape notation to output a quote
You can use this formula (Start trim for 1, in my case was 4):
=IF(ISBLANK([EUR Amount]),"",(TRIM(MID([EUR Amount],4,2))&TRIM(MID([EUR Amount],6,2))&TRIM(MID([EUR Amount],8,2))&TRIM(MID([EUR Amount],10,2))&TRIM(MID([EUR Amount],12,2))&TRIM(MID([EUR Amount],14,2)))*1)