I have an xsl file which I am currently grabbing all of the records from at once, starting them off as hidden and showing them as the user selects an id (<xsl:for-each select"">). The id value is currently being stored as a javascript variable selected by a user clicking that id.
I would like to use xQuery to grab the records, but only the records which match the ID the user has selected. Furthermore I generally understand the logic behind the rules in xQuery i just don't understand how to actually use it in my xsl file. Is it possible to use xQuery to maybe compare the value of the id(a js variable) to something using xQuery to grab only the records with that matching id?
Thank you for your time,
XQuery is a separate language from XSLT, not one that's embedded within XSLT. So depending on how you are launching XSLT, you can look for a parallel method for launching XQuery. For example, you may try XQIB (I have not tried it, but it looks promising).
If you need more help on that, let us know how you are running an XSLT processor, and what your data source is.
HOWEVER... It's not at all clear that XQuery is really what you want. It doesn't sound like you're wanting XQuery for something that you couldn't already do in XSLT. I'm not even sure you're not thinking of jQuery... which is a completely different animal.
It would be helpful if you could tell us more about where the records are coming from; what form they're stored in (an XML DOM?); and what you need to do with them. Probably the best solution then is that we show you how to do what you're trying to do within XSLT (or in Javascript).
Update
Looking at your new comment, I realize that I may have misunderstood where you are trying to run XQuery. You mentioned javascript above, from which I assumed you wanted to run XQuery in the browser, but now I think I jumped to the wrong conclusion - you are actually wanting to run it on the server maybe?
Regardless of where you're running it, either XSLT or XQuery can select "only the records which match the ID the user has selected". But if the XSLT/XQuery is running on the server, in order for this to work, you have to have either a page refresh or an AJAX call after the user selects an ID, to let the program on the server know what the selected ID is. I'm not sure if you already have that architecture set up, or if you're still trying to figure out how to use an AJAX call to retrieve data based on user input.
It sounds like you want to never send the whole set of records from server to client, not even initially (correct?). In that case, how does the user know what the set of available IDs is?
Anyway, you question may boil down to "How do you run XQuery from ASP.NET?" I have not tried to do that, but this article may help: Using Saxon.NET in ASP.NET; or this one: Querying XML Data with XQuery.
But again, I think XQuery may not be what you want. XQuery is not a querying language used within XSLT - that's more like XPath. XQuery is something you would use instead of XSLT, or beside it. So if you're using XSLT and you want to filter records according to what ID the user has selected, assuming you already know what ID the user has selected, the easy way to do that is within XSLT/XPath, rather than firing up a separate processor. E.g. you could say
<xsl:for-each select="//record[#ID = $usersChosenID]"> ...
Let me know if this is getting close to a solution for you. There are a variety of directions to expand this explanation, but I don't want to spend time scratching where there's no itch.
Related
I'm helping develop a new API for an existing database.
I'm using Python 2.7.3, Django 1.5 and the django-rest-framework 2.2.4 with PostgreSQL 9.1
I need/want good documentation for the API, but I'm shorthanded and I hate writing/maintaining documentation (one of my many flaws).
I need to allow consumers of the API to add new "POS" (points of sale) locations. In the Postgres database, there is a foreign key from pos to pos_location_type. So, here is a simplified table structure.
pos_location_type(
id serial,
description text not null
);
pos(
id serial,
pos_name text not null,
pos_location_type_id int not null references pos_location_type(id)
);
So, to allow them to POST a new pos, they will need to give me a "pos_name" an a valid pos_location_type. So, I've been reading about this stuff all weekend. Lots of debates out there.
How is my API consumers going to know what a pos_location_type is? Or what value to pass here?
It seems like I need to tell them where to get a valid list of pos_locations. Something like:
GET /pos_location/
As a quick note, examples of pos_location_type descriptions might be: ('school', 'park', 'office').
I really like the "Browseability" of of the Django REST Framework, but, it doesn't seem to address this type of thing, and I actually had a very nice chat on IRC with Tom Christie earlier today, and he didn't really have an answer on what to do here (or maybe I never made my question clear).
I've looked at Swagger, and that's a very cool/interesting project, but take a look at their "pet" resource on their demo here. Notice it is pretty similar to what I need to do. To add a new pet, you need to pass a category, which they define as class Category(id: long, name: string). How is the consumer suppose to know what to pass here? What's a valid id? or name?
In Django rest framework, I can define/override what is returned in the OPTION call. I guess I could come up with my own little "system" here and return some information like:
pos-location-url: '/pos_location/'
in the generic form, it would be: {resource}-url: '/path/to/resource_list'
and that would sort of work for the documentation side, but I'm not sure if that's really a nice solution programmatically. What if I change the resources location. That would mean that my consumers would need to programmatically make and OPTIONS call for the resource to figure out all of the relations. Maybe not a bad thing, but feels like a little weird.
So, how do people handle this kind of thing?
Final notes: I get the fact that I don't really want a "leaking" abstaction here and have my database peaking thru the API layer, but the fact remains that there is a foreign_key constraint on this existing database and any insert that doesn't have a valid pos_location_type_id is raising an error.
Also, I'm not trying to open up the URI vs. ID debate. Whether the user has to use the pos_location_type_id int value or a URI doesn't matter for this discussion. In either case, they have no idea what to send me.
I've worked with this kind of stuff in the past. I think there is two ways of approaching this problem, the first you already said it, allow an endpoint for users of the API to know what is the id-like value of the pos_location_type. Many API's do this because a person developing from your API is gonna have to read your documentation and will know where to get the pos_location_type values from. End-users should not worry about this, because they will have an interface showing probably a dropdown list of text values.
On the other hand, the way I've also worked this, not very RESTful-like. Let's suppose you have a location in New York, and the POST could be something like:
POST /pos/new_york/
You can handle /pos/(location_name)/ by normalizing the text, then just search on the database for the value or some similarity, if place does not exist then you just create a new one. That in case users can add new places, if not, then the user would have to know what fixed places exist, which again is the first situation we are in.
that way you can avoid pos_location_type in the request data, you could programatically map it to a valid ID.
I want to insert a URL filter and I would like the URL to be hard to dechiffre.
For example .*porn\.* in a way maybe that it uses the ASCII code for the letters in hex form .
Of course, the example is obvious and I definately will leave that one as it is ;)
But for the others I would like them to be hard to read!
Thx!
You can use the $_GET function in PHP to pull an ID out of the URL and display it that way, similar to Youtube with their "watch?v=". I recently did one using "?id=49" (I only have a few pages ATM, I will have about 70 soon). What I did is use a database with a song_id to index the information. I use the same basic layout, but you can use the ID to access information wrapped in PHP so that it doesnt get sent to the browser but will still display the page you want.
Or if you really want it to look crazy, you could use a database using the SHA() or MD5() function to encrypt it.
and your display will look like /page.php?id=21a57f2fe765e1ae4a8bf15d73fc1bf2a533f547f2343d12a499d9c0592044d4.
Say I request
parent/child/child/page-name
in my browser. I want to extract the parent, children as well as page name. Here are the regular expressions I am currently using. There should be no limit as to how many children there are in the url request. For the time being, the page name will always be at the end and never be omitted.
^([\w-]{1,}){1} -> Match parent (returns 'parent')
(/(?:(?!/).)*[a-z]){1,}/ -> Match children (returns /child/child/)
[\w-]{1,}(?!.*[\w-]{1,}) -> Match page name (returns 'page-name')
The more I play with this, the more I feel how clunky this solution is. This is for a small CMS I am developing in ASP Classic (:(). It is sort of like the MVC routing paths. But instead of calling controllers and functions based on the URL request. I would be travelling down the hierarchy and finding the appropriate page in the database. The database is using the nested set model and is linked by a unique page name for each child.
I have tried using the split function to split with a / delimiter however I found I was nested so many split statements together it became very unreadable.
All said, I need an efficient way to parse out the parent, children as well as page name from a string. Could someone please provide an alternative solution?
To be honest, I'm not even sure if a regular expression is the best solution to my problem.
Thank you.
You could try using:
^([\w-]+)(/.*/)([\w-]+)$
And then access the three matching groups created using Match.SubMatches. See here for more details.
EDIT
Actually, assuming that you know that [\w-] is all that is used in the names of the parts, you can use ^([\w-]+)(.*)([\w-]+)$ instead and it will handle the no-child case fine by itself as well.
I'm taking over a project and wanted to understand if this is common practice using SOAP. The process that is currently in place I have to query all the values before I do an update cause I need to pass back all the values that are not being updated. Does this sound right?
Example Values:
fname=phill
lname=pafford
address=123 main
phone:222-555-1212
So if I just wanted to update the phone number I need to query for the record, get all the values and submit these values for an update.
Example Update Values:
fname=phill
lname=pafford
address=123 main
phone:111-555-1212
I just want to know if this is common practice or should I change the functionality of this?
This is not specific to SOAP. It may simply be how the service is designed. In general, there will be fields that can only be updated if you have the original value: you can't add one to a field unless you know the original value, for instance. The service seems to have been designed for the general case.
I don't think that it is a very "common" practice. However I've seen cases where the old values are posted together with the new values, in order to validate that noone else has updated the values in the meantime.
I have the following for-each select;
"sc:item($myFolder,.)/descendant::item [#template='myTemplate']". According to Sitecore's own profiler this returns crawls through 16.000 items, although there are only approx 1700 items with the mentioned template.
Could this be optimized - if so, how?
The for-each is not the problem, but the XPath query used is.
The descendant axis is usually expensive because it requires the engine to do a complete deep search, without the possibility of eliminating paths. So you may want to replace this with a pattern which restricts the required search path.
Maybe using keys would help, but without deeper knowledge of the XML to be processed and the operations performed this is hard to tell.
If you can convert your xsl:for-each to a xsl:template, it should help with performance, as most XSLT processors are optimized for template matching.
"Do you have an example of this? It's a basic for-each that select a list of items based on the template, and then sort by a number field and shows the 3 top (so its basicly a top 3 list)"
Based on what you're trying to accomplish, I think you would be much better off putting this logic into a save handler and organizing your items when a content author saves an item based on the template you're looking for.
For example (and this is a very rough example), create a "Top 3" folder in your content tree. Then, write a save handler that checks the TemplateID of an item as it's being saved. If the saved item's TemplateID matches the TemplateID you're looking for, select all the items in your tree based on the TemplateID and process them with whatever sorting logic you need. As you find an item that belongs in the "Top 3" folder, move the item to the "Top 3" folder.
Then, in your rendering code, you simply have to get the "Top 3" folder and retrieve it's children. This will be MUCH faster than attempting to look through 1700 items every time the rendering is loaded.
If I need to do any particularly difficult searches in an XSLT, then I often define an XSLT helper method to perform the search, as the .Net API has much better facilities available.
In your case, I'd consider creating a .Net function to do the job, either using the Link Manager (as Mark Cassidy suggests) or using Sitecore fast queries to retrieve the items (fast queries are parsed and run as SQL queries).
To register a class as an XML Extension Method library, open web.config, locate the /configuration/sitecore/xslExtensions node and add an entry with your class' full type name and an XML namespace (the URL doesn't actually have to exist).
To use your function, register it in the namespaces at the top of your XSLT (and remember to add the namespace to the exclude-result-prefixes stylesheet attribute). You should then be able to call `namespace:YourFunction().
For more detailed information on XSLT extension methods, see the presentation component reference, page 40.
The reason the XSLT crawls through 16,000 items when you only have 1700 matches is that the 16,000 represents the number of nodes tested, not the number of nodes returned. Sitecore XSLT performance is dependent on your actual data structure, if you have a flat structure with lots of nodes (e.g. everything in one folder) all xslt processing will suffer. You might consider optimising your data structure into something deeper and more branched to aid XSLT performance. I believe Sitecore themselves recommend that you have no more than 100 items in any location (i.e. never more than 99 siblings for any item).
It can be optimised, but the easiest approach would be to reorganize your content architecture to better suit your needs and requirements.
Straight from XSLT there is no easy solution, but with a bit of coding you can fAirly easily get all your content items based on your specific template. It would look something like this:
Item myTemplate = Sitecore.Context.Database.GetItem( "id-of-your-template" );
LinkItem[] li = Sitecore.Globals.LinkDataBase.GetReferrers( myTemplate );
// li now holds a list of LinkItem for items that are based on your template
List<Item> myItems = new List<Item>();
foreach( LinkItem l in li )
myItems.Add( li.SourceItem() );
// your additional processing/filtering here
Keep in mind, this is a very non-specific example of how this can be achieved. I would need to know a lot more about your solution to come up with a better response. And I still feel, the best approach is probably still to look at your information architecture.