Linq query not matching hrefs - regex

I'm trying to write out all matches found using a regex with the code below:
var source = "<Content><link><a xlink:href=\"tcm:363-48948\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">Read more</a></link><links xlink:href=\"tcm:362-65596\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"/></Content>";
var tridionHref = new Regex("tcm:([^\"]*)");
var elem = XElement.Parse(source);
XNamespace xlink = "http://www.w3.org/1999/xlink";
if (tridionHref.IsMatch(elem.ToString()))
{
foreach (var Id in elem.Elements().Where(x => x.Attribute(xlink + "href") != null))
{
Console.WriteLine(Id.Attribute(xlink + "href").Value); //For testing
Id.Attribute(xlink + "href").Value = Id.Attribute(xlink + "href").Value.Replace("value1", "value2"); //Just to show you an example
}
}
My console window outputs tcm:362-65596 but not tcm:363-48948. It looks like the code doesn't see the value of xlink:href inside my <a> tag as an attribute? Can anyone point me in the right direction? I need to match ALL instances of tcm:([^\"]*).

The problem is you are not looking in the right place. Your elem.Elements is looking at the link element and the links element. Only one of these has the attribute that you are looking for. You'll need to select the elements you want to check more precisely before looking for the right attribute.

I've got it working. I didn't need a regex I just needed to get the Descendants instead inside my for loop. foreach (var Id in elem.Descendants().Where(x => x.Attribute(xlink + "href") != null))

Related

Insert list item into a specific Table of google doc

This is the point.
I've followed the suggest linked here More efficient way to append a list item after some text in Google Docs ,whose very helpfull tom me. But i have the problem mentioned at the bottom.
My placeholder is inside a known table within a google doc.
I've tried several ways to figure it out, but i didn't achieve.
Here below there is the portion of code of interest.
Note:
"CarattCentralGas1" is an array of values;
"DescrizioneCentralGas" is another array of values;
My intent is to insert a list, created if the if condition is true, at the placeholder place and than remove it.
Any ideas would be great!`
for (var i=0; i < CarattCentraleGas1.length; ++i)
{ var ValueToTest = CarattCentraleGas1[i][0];
Logger.log(ValueToTest)
if (ValueToTest ==='Presente')
{ var valueToextract = DescrizioniCentraleGas[i][0];
var search = '%Placeholder%';
var Table1 = body.getTables()[0];
var found = Table1.findText(search);
while (found) {
var elem = found.getElement().getParent().getParent();
var index = Table1.getChildIndex(elem);
Table1.insertListItem(index+1, valueToextract+';');
found = Table1.findText(search, found);}
Logger.log(valueToextract)}
}
var Table1Text = Table1.editAsText().replaceText('%CarattCentrale1%',"");
`
this is the template document I want to edit with the script.

Replace parts of a URL in Greasemonkey

I'm trying to replace a part of url using a Greasemonkey script, but having hard time to achieve what I'm trying to do.
Original Urls are like:
http://x1.example.to/images/thumb/50/157/1571552600.jpg
http://x2.example.to/images/thumb/50/120/1201859695.jpg
http://x3.example.to/images/thumb/50/210/2109983330.jpg
What I want to achieve is this:
http://example.to/images/full/50/157/1571552600.jpg
http://example.to/images/full/50/120/1201859695.jpg
http://example.to/images/full/50/210/2109983330.jpg
I just want to replace thumb with full and cut out the x1.example.to, x2.example.to, x3.example.to, x4.example.to etc.. part completely from the original URL so new urls will be starting like example.to/images/full/
How do I achieve this?
I have found a Greasemonkey script from this answer and did try to work out but failed.
Here's what i did so far.
// ==UserScript==
// #name Example Images Fixer
// #namespace Example
// #description Fixes image galleries
// #include http://*.example.to/*
// ==/UserScript==
var links = document.getElementsByTagName("a"); //array
var regex = /^(http:\/\/)([^\.]+)(\.example\.to\/images\/thumb/\)(.+)$/i;
for (var i=0,imax=links.length; i<imax; i++) {
links[i].href = links[i].href.replace(regex,"$4full/$5");
}
Any help on that?
You're forgetting to put the http:// part in your replacement URL:
/^(https?:\/\/)[^.]+\.(example\.to\/images\/)thumb\/(.+)$/i
and then:
.replace(regex, "$1$2full/$3");
You can see the results here.
Here is an example of what can be done:
var urls = ['http://x1.example.to/images/thumb/50/157/1571552600.jpg',
'http://x2.example.to/images/thumb/50/120/1201859695.jpg',
'http://x3.example.to/images/thumb/50/210/2109983330.jpg'];
for (var i = 0, len = urls.length; i < len; i++) {
urls[i] =
urls[i].replace(/:\/\/[^\.]+\.(example.to\/images\/)thumb/, '://$1full');
console.log(urls[i]);
}
/* result
"http://example.to/images/full/50/157/1571552600.jpg"
"http://example.to/images/full/50/120/1201859695.jpg"
"http://example.to/images/full/50/210/2109983330.jpg"
*/
Here is the Fiddle

How do I query multiple IDs via the ContentSearchManager?

When I have an array of Sitecore IDs, for example TargetIDs from a MultilistField, how can I query the ContentSearchManager to return all the SearchResultItem objects?
I have tried the following which gives an "Only constant arguments is supported." error.
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(x => f.TargetIDs.Contains(x.ItemId));
rpt.DataBind();
}
I suppose I could build up the Linq query manually with multiple OR queries. Is there a way I can use Sitecore.ContentSearch.Utilities.LinqHelper to build the query for me?
Assuming I got this technique to work, is it worth using it for only, say, 10 items? I'm just starting my first Sitecore 7 project and I have it in mind that I want to use the index as much as possible.
Finally, does the Page Editor support editing fields somehow with a SearchResultItem as the source?
Update 1
I wrote this function which utilises the predicate builder as dunston suggests. I don't know yet if this is actually worth using (instead of Items).
public static List<T> GetSearchResultItemsByIDs<T>(ID[] ids, bool mustHaveUrl = true)
where T : Sitecore.ContentSearch.SearchTypes.SearchResultItem, new()
{
Assert.IsNotNull(ids, "ids");
if (!ids.Any())
{
return new List<T>();
}
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var predicate = PredicateBuilder.True<T>();
predicate = ids.Aggregate(predicate, (current, id) => current.Or(p => p.ItemId == id));
var results = s.GetQueryable<T>().Where(predicate).ToDictionary(x => x.ItemId);
var query = from id in ids
let item = results.ContainsKey(id) ? results[id] : null
where item != null && (!mustHaveUrl || item.Url != null)
select item;
return query.ToList();
}
}
It forces the results to be in the same order as supplied in the IDs array, which in my case is important. (If anybody knows a better way of doing this, would love to know).
It also, by default, ensures that the Item has a URL.
My main code then becomes:
var f = (Sitecore.Data.Fields.MultilistField) rootItem.Fields["Main navigation links"];
rpt.DataSource = ContentSearchHelper.GetSearchResultItemsByIDs<SearchResultItem>(f.TargetIDs);
rpt.DataBind();
I'm still curious how the Page Editor copes with SearchResultItem or POCOs in general (my second question), am going to continue researching that now.
Thanks for reading,
Steve
You need to use the predicate builder to create multiple OR queries, or AND queries.
The code below should work.
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var predicate = PredicateBuilder.True<SearchResultItem>();
foreach (var targetId in f.Targetids)
{
var tempTargetId = targetId;
predicate = predicate.Or(x => x.ItemId == tempTargetId)
}
rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(predicate);
rpt.DataBind();
}

ASP.NET MVC Custom route regex to catch a substring of items and check for their existence

I'm trying to create a custom route for URL with the following format:
http://domain/nodes/{item_1}/{item_2}/{item3_}/..../{item_[n]}
Basically, there could be a random amount of item_[n], for example
http://domain/nodes/1/3/2
http://domain/nodes/1
http://domain/nodes/1/25/11/45
With my custom route I would like to retrieve an array of items and do some logic (validate and add some specific information to request context) with them.
For example from [http://domain/nodes/1/25/11/45] I would like to get an array of [1, 25, 11, 45] and process it.
So, I have 2 problems here.
The first one is a question actually. Am I looking in the right direction? Or there could be an easier way to accomplish this (maybe without custom routes)?
The second problem is matching incoming url with a regex pattern. Could someone help me with it?
Thanks in advance :)
To solve your problem I think that a way could be to create a routing class and then handle the params accordinlgy.
public class CustomRouting : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
var repository = new FakeRouteDB(); //Use you preferred DI injector
string requestUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath;
string[] sections = requestUrl.Split('/');
/*
from here you work on the array you just created
you can check every single part
*/
if (sections.Count() == 2 && sections[1] == "")
return null; // ~/
if (sections.Count() > 2) //2 is just an example
{
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Products");
result.Values.Add("action", "Edit");
result.Values.Add("itmes0", sections[1]);
if (sections.Count() >= 3)
result.Values.Add("item2", sections[2]);
//....
}
else
{
//I can prepare a default route
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Home");
result.Values.Add("action", "Index");
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//I just work with outbound so it's ok here to do nothing
return null;
}
}
In the global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new CustomRouting());
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
This should give you an idea of what I think. Hope it helps
I can't help you with the first part of your question, but I can have a go at creating the regex.
In your example all the items are digits - is that the only option ? If not, please provide more info on possible characters.
For now the regex would be:
#"http://domain/nodes(?:/(\d+))*"
(?:) is a non capturing group, () is a capturing group.
If you match all occurences, then you'll end up with groups 1-n, where each group will contain the matched number (group number 0 will be the whole match).

CFGRID - replace data store or filter on more than one column

ColdFusion 8
I have a cfgrid that that is based on a query. It is not bound to a cfc function because I want a scrolling grid, not a paged grid (you must supply the page number and page size if you use BIND).. I can figure out how to make it filter on one column by using the following code, but I really need to filter on three columns...
grid.getDataSource().filter("OT_MILESTONE",t1);
Adding more to the filter string does not do the trick...it ignores anything more than the first pair of values..
so..I thought if I called a function that passes the three values and returned the query results to me, I could replace the Data Store for the grid..but I cannot figure out the syntax to get it to replace.
The returned variable for the query has the following format:
{"COLUMNS":["SEQ_KEY","ID","OT_MILESTONE"],"DATA":[[63677,"x","y"]]}
Any ideas?
have you looked at queryconvertforgrid()?
http://www.cfquickdocs.com/cf9/#queryconvertforgrid
Update: have you looked at these?
http://www.danvega.org/blog/index.cfm/2008/3/10/ColdFusion-8-Grid-Filtering
http://www.coldfusion-ria.com/Blog/index.cfm/2009/1/13/Playing-with-cfgrid--Filter-showhide-Columns-and-using-the-YUI-Buttons-library
http://cfsilence.com/blog/client/index.cfm/2007/8/9/Filtering-Records-In-An-Ajax-Grid
after much blood, sweat, tears and swearing..here's the answer, in case anyone else might need to filter a cfgrid by more than one variable:
var w1 = ColdFusion.getElementValue('wbs');
var t1 = ColdFusion.getElementValue('task');
var p1 = ColdFusion.getElementValue('project');
grid = ColdFusion.Grid.getGridObject('data');
store = grid.getDataSource();
store.clearFilter();
store.filterBy(function myfilter(record) {
var wantit = true;
if (trim(w1) != '') {
if(record.get('WBS_ID') != w1) {
wantit = false;
}}
if (trim(t1) != '') {
if(record.get('OT_MILESTONE') != t1) {
wantit = false;
}}
if (trim(p1) != '') {
if(record.get('PROJECT') != p1) {
wantit = false;
}}
return wantit;
});
ColdFusion.Grid.refresh('data',false);
you will need a JS trim function...
Make sure the column names are caps...