xf:repeat nodeset poor performance - xquery

I fill in a table with xf:repeat nodeset element:
<tbody xf:repeat-nodeset="instance('table')//result">
<tr>
<td>
<xf:output value="interfaceName"></xf:output>
</td>
<td>
<xf:output value="reportDate"></xf:output>
</td>
<td>
<xf:group ref=".[testResult='success']">
<xf:output value="testResult" style="color:green;font-weight:bold"/>
</xf:group>
<xf:group ref=".[testResult='failure']">
<xf:output value="testResult" style="color:red;font-weight:bold"/>
</xf:group>
</td>
<td>
<xf:trigger appearance="minimal">
<xf:label>File link</xf:label>
<xf:action ev:event="DOMActivate">
<xf:load show="new">
<xf:resource value="fileLink"/>
</xf:load>
</xf:action>
</xf:trigger>
</td>
</tr>
</tbody>
Iterating over 600 results and filling in 4 columns takes 28 seconds. To my mind, it is way to much. Can anyone suggest how can I improve this?

Using // in an XPath expression might be a problem for some XForms engines, at least with XSLTForms, because XForms does not specify how to define an index to improve this. Without an index, all nodes are tested one by one!
You should try with the full path, if possible.

For read-only display of results like this, I find the transform() function supported by some processors very convenient. Write a stylesheet that accepts your 'result' instance as input and produces an HTML table; I'll call it 'results-to-table.xsl'. Then write
<xf:output value="transform(instance('results'),
'results-to-table.xsl',
false)"
mediatype="application/xhtml+xml"/>
at the appropriate location in your document.
Since transform() is not standard in XForms 1.1, this will only work in processors that accept it as an extension to the language; XSLTForms does, but I don't know what other processors do.

Related

Is it possible to pass class to binding attribute in Angular?

We have a solution based on a numeric field being set to 1 or 2 or displaying certain icons. It works.
<span *ngIf="config.icon"
[class.fas]="true"
[class.fa-plus]="icon===1"
[class.fa-minus]="icon===2"
class="indicator">
</span>
I sense what shortly, we'll have a whole bunch of such icons (about 15 different ones). The suggested solution is either to put in 15 lines of specific class assignments or to build a specialized component managing that.
I'm opposed to both but haven't got it working out when I tried and googling led to irrelevant hits. Possibly due to my incompetence recognized th egood stuff.
Is it possible to do something like one of the following pseudo code lines? How?
[class.fa-{{iconName}}]="true"
[class]="iconName"
edit
Based on the comments/answers, I got it working using the following.
<span *ngIf="config.icon"
[ngClass]='{ "fas": true, "fa-plus": true }'></span>
However, for some reason, I'm not getting anything using the syntax below.
<span *ngIf="config.icon"
[ngClass]="classes"></span>
...
classes: { "fas": true, "fa-plus": true };
What am I missing?
You can try something like this:
<span class= "indicator"
[class.fas]="true"
[ngClass]="'fa-' + iconName">
</span>
See working example at https://stackblitz.com/edit/angular-mgecjw

Proper usage of string.Format to format an EVAL

I've got a (probably) simple question, just can't seem to work this out. I've got a repeater and I want to show tracks on a CD. My code looks like this:
<td><%(string.Format("{0:00}", #EVAL("TrackNo")) %>: <%#Eval("SongName") %></td>
Everything was working perfect before I started putzing with the format piece, I want the tracks to line up like:
01
02
...
09
10
instead of
1
2
...
9
10
What am I doing wrong? The field TrackNo is an INT, so I read that it might need to be converted to an int first?
I think it should work;
<%# string.Format("{0:00}", (Convert.ToInt32(Eval("TrackNo"))) %>
or
<%# (Convert.ToInt32(Eval("TrackNo"))).ToString("00") %>

R web scraper with jsessionid

I'm testing some web scrape scripts in R. I've read many tutorials, docs and tried different things but no success so far.
The URL I'm trying to scrape is this one. It has public, government data, and no statements against web scrapers. It's in Portuguese, but I believe it won't be a big problem.
It shows a search form, with several fields. My test was searching for data from a particular state ("RJ", in this case the field is "UF"), and city ("Rio de Janeiro", in the field "MUNICIPIO"). By clicking "Pesquisar" (Search), it shows the following output:
Using Firebug, I found the URL it calls (using the parameters above) is:
http://www.dataescolabrasil.inep.gov.br/dataEscolaBrasil/home.seam?buscaForm=buscaForm&codEntidadeDecorate%3AcodEntidadeInput=&noEntidadeDecorate%3AnoEntidadeInput=&descEnderecoDecorate%3AdescEnderecoInput=&estadoDecorate%3A**estadoSelect=33**&municipioDecorate%3A**municipioSelect=3304557**&bairroDecorate%3AbairroInput=&pesquisar.x=42&pesquisar.y=16&javax.faces.ViewState=j_id10
The site uses a jsessionid, as can be seen using the following:
library(rvest)
library(httr)
url <- GET("http://www.dataescolabrasil.inep.gov.br/dataEscolaBrasil/")
cookies(url)
Knowing it uses a jsessionid, I used cookies(url) to check this info, and used it into a new URL like this:
url <- read_html("http://www.dataescolabrasil.inep.gov.br/dataEscolaBrasil/home.seam;jsessionid=008142964577DBEC622E6D0C8AF2F034?buscaForm=buscaForm&codEntidadeDecorate%3AcodEntidadeInput=33108064&noEntidadeDecorate%3AnoEntidadeInput=&descEnderecoDecorate%3AdescEnderecoInput=&estadoDecorate%3AestadoSelect=org.jboss.seam.ui.NoSelectionConverter.noSelectionValue&bairroDecorate%3AbairroInput=&pesquisar.x=65&pesquisar.y=8&javax.faces.ViewState=j_id2")
html_text(url)
Well, the output doesn't have the data. In fact, it has a error message. Translated into English, it basically says the session was expired.
I assume it is a basic mistake, but I looked all around and couldn't find a way to overcome this.
This combination worked for me:
library(curl)
library(xml2)
library(httr)
library(rvest)
library(stringi)
# warm up the curl handle
start <- GET("http://www.dataescolabrasil.inep.gov.br/dataEscolaBrasil/home.seam")
# get the cookies
ck <- handle_cookies(handle_find("http://www.dataescolabrasil.inep.gov.br/dataEscolaBrasil/home.seam")$handle)
# make the POST request
res <- POST("http://www.dataescolabrasil.inep.gov.br/dataEscolaBrasil/home.seam;jsessionid=" %s+% ck[1,]$value,
user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:40.0) Gecko/20100101 Firefox/40.0"),
accept("*/*"),
encode="form",
multipart=FALSE, # this gens a warning but seems to be necessary
add_headers(Referer="http://www.dataescolabrasil.inep.gov.br/dataEscolaBrasil/home.seam"),
body=list(`buscaForm`="buscaForm",
`codEntidadeDecorate:codEntidadeInput`="",
`noEntidadeDecorate:noEntidadeInput`="",
`descEnderecoDecorate:descEnderecoInput`="",
`estadoDecorate:estadoSelect`=33,
`municipioDecorate:municipioSelect`=3304557,
`bairroDecorate:bairroInput`="",
`pesquisar.x`=50,
`pesquisar.y`=15,
`javax.faces.ViewState`="j_id1"))
doc <- read_html(content(res, as="text"))
html_nodes(doc, "table")
## {xml_nodeset (5)}
## [1] <table border="0" cellpadding="0" cellspacing="0" class="rich-tabpanel " id="j_id17" sty ...
## [2] <table border="0" cellpadding="0" cellspacing="0">\n <tr>\n <td>\n <img alt="" ...
## [3] <table border="0" cellpadding="0" cellspacing="0" id="j_id18_shifted" onclick="if (RichF ...
## [4] <table border="0" cellpadding="0" cellspacing="0" style="height: 100%; width: 100%;">\n ...
## [5] <table border="0" cellpadding="10" cellspacing="0" class="dr-tbpnl-cntnt-pstn rich-tabpa ...
I used BurpSuite to inspect what was going on and did a quick test at the command line with the output from "Copy as cURL" and adding --verbose to I could validate what was being sent/received. I then mimicked the curl parameters.
By starting at the bare search page, the cookies for the session id and the bigip server are already warmed up (i.e. will be sent with every request so you don't have to mess with them) BUT you still need to fill it in on the URL path so we have to retrieve them, then fill it in.

Rails 4: how to identify and format links, hashtags and mentions in model attributes?

In my Rails 4 app, I have a Post model, with :copy and :short_copy as custom attributes (strings).
These attributes contain copies for social medias (Facebook, Twitter, Instagram, Pinterest, etc.).
I display the content of these attributes in my Posts#Show view.
Currently, URLs, #hashtags and #mentions are formatted like the rest of the text.
What I would like to do is to format them in a different fashion, for instance in another color or in bold.
I found the twitter-text gem, which seems to offer such features, but my problem is that I do NOT need — and do NOT want — to have these URLs, #hashtags and #mentions turn into real links.
Indeed, it looks like the twitter-text gem converts URLs, #hashtags and #mentions by default with Twitter::Autolink, as explained in this Stack Overflow question.
That's is not what I am looking for: I just want to update the style of my URLs, #hashtags and #mentions.
How can I do this in Ruby / Rails?
—————
UPDATE:
Following Wes Foster's answer, I implemented the following method in post.rb:
def highlight(string)
string.gsub!(/\S*#(\[[^\]]+\]|\S+)/, '<span class="highlight">\1</span>')
end
Then, I defined the following CSS class:
.highlight {
color: #337ab7;
}
Last, I implemented <%= highlight(post.copy) %> in the desired view.
I now get the following error:
ArgumentError
wrong number of arguments (1 for 2..3)
<td><%= highlight(post.copy) %></td>
What am I doing wrong?
—————
I'm sure each of the following regex patterns could be improved to match even more options, however, the following code works for me:
def highlight_url(str)
str.gsub!(/(https?:\/\/[\S]+)/, '[\1]')
end
def highlight_hashtag(str)
str.gsub!(/\S*#(\[[^\]]+\]|\S+)/, '[#\1]')
end
def highlight_mention(str)
str.gsub!(/\B(\#[a-z0-9_-]+)/i, '[\1]')
end
# Initial string
str = "Myself and #doggirl bought a new car: http://carpictures.com #nomoremoney"
# Pass through each
highlight_mention(str)
highlight_hashtag(str)
highlight_url(str)
puts str # > Myself and [#doggirl] bought a new car: [http://carpictures.com] [#nomoremoney]
In this example, I've wrapped the matches with brackets []. You should use a span tag and style it. Also, you can wrap all three gsub! into a single method for simplicity.
Updated for the asker's add-on error question
It looks like the error is references another method named highlight. Try changing the name of the method from highlight to new_highlight to see if that fixes the new problem.

How to convert ticks into a readable datetime with XSLT?

I have an XML with timestamps like this:
<node stamp="1236888746689" />
And I would like to display them in the result HTML as date with time.
Is there a way to do it with XSLT (any Version)?
EDIT:
I am using XSLT2.0 with Saxon9. The base date is 1970-01-01 0:00.
You take the date 1970-01-01T00:00:00 and add as many milliseconds as the value of the stamp tells you:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/TR/xhtml1/strict">
<xsl:template match="node">
<xsl:value-of
select='xs:dateTime("1970-01-01T00:00:00") + #stamp * xs:dayTimeDuration("PT0.001S")'/>
</xsl:template>
</xsl:stylesheet>
If you are using an XSLT 1.0 processor which supports the EXSLT date functions (I've just tested this with libxslt in PHP), you can use date:add() and date:duration():
<xsl:value-of select="date:add('1970-01-01T00:00:00Z', date:duration(#stamp div 1000))"/>
The date:duration() function takes a number of seconds (so you have to divide your milliseconds by 1000) and turns it into a "duration" (in this case, "P14315DT20H12M26.6889998912811S"), which is then added to the start of your epoch (looks like the standard epoch, for this stamp) with date:add() to get a stamp of "2009-03-12T20:12:26.6889998912811Z". You can then format this using the EXSLT date functions or just substring(), depending on what you need.
Belated answer, yes, I know, but I couldn't find the one I was looking for here, so I thought I'd pay it forward with my solution.
My XML was a few nodes dumped from Drupal using export_node and drush. I was using the xslt processor in PHP5, which only supports xslt 1.0. Some EXSLT functions appear to be supported, but I couldn't tell whether my syntax was wrong or the function I was trying to use was not supported. Anyway, the following worked for me. I used the example code from w3schools.com, but added a line right after declaring the xsltprocessor, like below:
$xp = new XsltProcessor();
$xp->registerPHPFunctions();
PHP has a trivial function for date conversion, so I cheated and used the PHP processor, since I was already using it to transform my xsl.
<xsl:for-each select="node_export/node">
<xsl:value-of select="php:function('date', 'n-j-y', number(timestamp))"/>
</xsl:for-each>
Hope this helps someone out there. I was banging my head for quite a while as I worked this one out.
If you wanted to use an XSL 1.0 processor that does not support the EXSLT date and time functions this is non-trivial, but it has been done.
You can have a look at Katy Coe's XSLT 1.0 implementation of the "iso-from-unix" function. It's part of a rather huge "free for non-commercial use" set of date and time functions she created.
However, your XSL processor must support the "http://exslt.org/functions" namespace for this implementation to work. Other than that there is no dependency on EXSLT.
P.S.: I'm aware that a Unix timestamp and ticks are not exactly the same thing. They are close enough, though.
XSLT is Turing complete, so there must be a way. :) Knowing at least a bit of XSLT, it will probably involve recursion.
You don't specify the exact interpretation of your "ticks", I'm guessing milliseconds since some epoch, but which? 1970?

Resources