if
/dt/#id
returns comment_34232 or comment_12 how can I make it return 34232 or 12 (in other words replaceing 'comment_' with ''
and if
/span/style
returns width: 80%; how can I replace width: and after that %; to retrieve 80
Regards
I. Part
if
/dt/#id returns `comment_34232` or `comment_12` how can I make it return
34232 or 12 (in other words
replaceing 'comment_' with ''
Use:
substring-after(/dt/#id, '_')
II. Part
and if
/span/style returns `width: 80%;` how can I replace `width: ` and after
that %; to retrieve 80
Use:
substring-before(substring-after(/span/style, ' '), '%')
Do note: the use of the standard XPath functions substring-before() and substring-after() .
Related
Why this
SELECT * FROM STUDENT
WHERE FULLNAME LIKE 'Nguyen' || '%'
as the same
SELECT * FROM STUDENT
WHERE FULLNAME LIKE 'Nguyen%'
How does the first one work?
|| is concatenation operator. Oracle will first perform concatenation and then will use LIKE to match the pattern. Hence operationally it will be same as the second one.
However you should use the second one as it will be more efficient in performance and easy to read.
First one has extra overhead to append two strings before using LIKE to match the pattern.
the first one catenate 'Nguyen' and '%' through the pipes '||' in first place.
Because you don't have any space like 'Nguyen ' or ' %', it's the same as 'Nguyen%'.
There is no difference between these two:
Here the double pipe(||) is just a concatenation of expression.
Before db evaluate against like parameter, it concatenates
Hence both of those are same.
Both are same, as || operator concats 'Nguyen' and '%', it will be more helpful if you want to concat parameterize variable like below
SELECT * FROM STUDENT
WHERE FULLNAME LIKE :name || '%'
I need to parse a CSS file to to get individual selectors that contain a right or left word in their declarations(block). And add the selectors and their corresponding declarations(block) to an Array or Hash. For example:
.selector-one { /* This selector and its declaration will be added */
.
.
float: right;
.
.
}
#selector-two { /* This selector and its declaration will be added */
.
.
margin-left: 20%;
.
.
}
I'm trying to write it using the scan method, This way:
content.scan(/.*?\{.*?(right|left).*?\}/)
Or
content.scan(/[^}]\{[^}](right|left)[^}]\}/)
But non of them work.
I should mention that:
It dosn't matter if the name of the selector contains the word left or right, We just need to check the blocks.
The name of the selectors may start with anything other than { or }
Selectors can be grouped, So we could have something like this:
.
h1, h2, p {
text-align: right;
color: red;
}
I don't know ruby but the regexp should be :
[{]([^}]*(right|left)[^}]*)[}]
With ungreedy,insensitive and global flags
Based on your sample, and if they aren't nested.
# \.(selector-[^{}]*?)\s*\{([^{}]*:[ ]*(?:right|left)[ ]*;[^{}]*)\}
\.
( selector- [^{}]*? ) # (1), Selector
\s*
\{
( # (2 start), Block
[^{}]*
: [ ]*
(?: right | left )
[ ]* ;
[^{}]*
) # (2 end)
\}
Output:
** Grp 0 - ( pos 0 , len 105 )
.selector-one { /* This block will be added to the array */
.
.
float: right;
.
.
}
** Grp 1 - ( pos 1 , len 12 )
selector-one
** Grp 2 - ( pos 15 , len 89 )
/* This block will be added to the array */
.
.
float: right;
.
.
----------------------
** Grp 0 - ( pos 196 , len 106 )
.selector-three { /* This block will be added to the array */
.
.
float: left;
.
.
}
** Grp 1 - ( pos 197 , len 14 )
selector-three
** Grp 2 - ( pos 213 , len 88 )
/* This block will be added to the array */
.
.
float: left;
.
.
Ruby's slice_before is handy for this:
blocks = DATA.each_line
.slice_before(/^\./)
.map(&:join)
.select{ |block| block[/\b(?:left|right)\b/] }
blocks
# => [".selector-one { /* This block will be added to the array */\n .\n .\nfloat: right;\n .\n .\n}\n\n",
# ".selector-three { /* This block will be added to the array */\n .\n .\nfloat: left;\n .\n .\n}\n"]
__END__
.selector-one { /* This block will be added to the array */
.
.
float: right;
.
.
}
.selector-two { /* This block wont be added to the array */
.
.
.
}
.selector-three { /* This block will be added to the array */
.
.
float: left;
.
.
}
each_line iterates over the lines in the file.
slice_before looks through the resulting array, and creates sub-arrays when the regular expression /^\./ matches a line that starts with ..
map(&:join) converts the contents of each sub-array back into a text string.
select looks inside each string and if /\b(?:left|right)\b/ matches the word "left" or "right", then the string is passed on.
It's important to use a pattern like /\b(?:left|right)\b/, because the string being searched for could be embedded in a longer string like 'leftover' or 'bright' and you don't want to get a false-positive.
You might not have seen __END__ and DATA before, but they're handy for test code like this. __END__ marks the end of the script, and anything after it can be treated as a pseudo data file, which is accessible via DATA. So consider the code to be reading from a file.
You could also use a CSS parser like Crass and scan the parse tree.
Spitballing code now...
tree = Crass.parse(css)
nodes_with_right_or_left = tree.select do |node|
node[:children] and node[:children].detect do |child|
child[:value] == "right" or child[:value] == "left"
end
end
YMMV :-)
Thanks to all the people answered to my question. Unfortunately non of them solve the problem. Here is how I implemented it:
input.scan(/[^{}]*\{[^}]*?(?:\Wright\W|\Wleft\W)[^}]*\}/)
The key was that the parentheses in scan method make a capture group. So we need to turn it into a non-capturing group, using ?:
I have following XML:
<root>
<chp id='1'>
<sent id='1'>hello</sent>
<sent id='2'>world</sent>
</chp>
<chp id='2'>
<sent id='1'>the</sent>
<sent id='2'>best</sent>
<sent id='3'>world</sent>
</chp>
</root>
Using the XPath expression
root/chp/sent[contains(.,'world')]/#id
I have the result 2 3 (which is exactly what I want), but when I run
concat('sentence ', /root/chp/sent[contains(.,'world')]/#id, ' - chap ' , /root/chp/sent[contains(.,'world')]/../#id )
the result breaks at the first result:
sentence 2 - chap 1
The last argument does not contain a single value, but a sequence. You cannot use XPath 1.0 to join this sequence to a single string. If you're able to use XPath 2.0, use string-join($sequence, $divisor):
concat(
'sentence ',
string-join(/root/chp/sent[contains(.,'world')]/#id, ' '),
' - chap ',
string-join(/root/chp/sent[contains(.,'world')]/../#id, ' ')
)
which will return
sentence 2 3 - chap 1 2
Most probably you want to loop over the result set yourself (also requires XPath 2.0):
for $sentence in /root/chp/sent[contains(.,'world')]
return concat('sentence ', $sentence/#id, ' - chap ', $sentence/../#id)
which will return
sentence 2 - chap 1
sentence 3 - chap 2
If you cannot use XPath 2.0, but are able to further process results in some outside programming language (like Java, PHP, ...) using DOM: Use /root/chp/sent[contains(.,'world')] to find the sentence nodes, loop over them, then query the #id and parent (chapter) #id using DOM and construct the result.
I want to get the node :
//script[starts-with(text(). '\r\nvar name')]
but it seems xpath does not recognize \r\n escape characters. Any ideas how to match them?
Note: I am using html agility pack
Use:
//script[starts-with(., '
var name')]
Most often XML is normalized by the XML parser and there is only a single NL character left -- therefore, if the above expression doesn't select the wanted script elements, try with:
//script[starts-with(., '
var name')]
Or, this would work in both cases:
//script
[(starts-with(., '
') or starts-with(., '
'))
and
starts-with(substring-after(., '
'), 'var name')
]
How to set the values for filter is explained here link text. I have two requirements.
1. the default value needs to be empty. I expect, if defaultValue is not set, the filter is empty, but that is not happening in my case.
2. How to escape ':' in my value. The character ':' and ';' are used to seperate the index and values. But, in my value string it contains a ':' (eg: searchoptions:{value:"1:'Level: 1'"} , where Level: 1 is my first value). How to escape : in the value part. I tried \ , / etc.
thanks.
Edit: Item 1 may be solved if there is no other way. I may set an additional item ALL in the values, and use it default.
You are right, it seems impossible to use any escape character to place ':' inside of value of searchoptions if you define it like a string:
searchoptions:{value:"1:'Level: 1'"}
There is another form of setting of value of searchoptions - object form, which is also described under http://www.trirand.com/jqgridwiki/doku.php?id=wiki:search_config#colmodel_options. For example you can use following syntax
searchoptions:{value:{'1:': 'Level: 1;', ':2:;': 'Level: 2;'}}
It defines a select with the texts "Level: 1;" and "Level: 2;" displayed and the corresponding values "1:" and ":2:;". It works.
I had the same issue and the only option was to use searchoptions object.
However, I had to programmatically build the list so I couldn't use define the objects.
Therefore, I decided to use build the list as an JSON string and then parse it, as shown below:
searchoptions: {
value: $.parseJSON("{" + searchSelectFormat.join(",") + "}"),
sopt: ['eq']
}
where searchSelectFormat is in the format of
'"' + data + '":"' + data + '"';
'"' + item+ '":"' + item+ '"'