Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#191 2013-09-26 15:34:51

mrdale
Moderator
From: Walla Walla
Registered: 2004-11-19
Posts: 2,203
Website

Re: etc_query: all things Textpattern

Here’s one. I want to reformat a mail chimp archive called on a page with javacript… it looks like this…

document.write("<div class=\"display_archive\"><div class=\"campaign\">09\/19\/2013 - <a href=\"http:\/\/us7.campaign-archive1.com\/?u=999&id=888\" title=\"Title 1\" target=\"_blank\">Title 1<\/a><\/div><div class=\"campaign\">09\/12\/2013 - <a href=\"http:\/\/us7.campaign-archive1.com\/?u=777&id=666\" title=\"Title 2\" target=\"_blank\">Title 2<\/a><\/div><\/div>");

So obviously I point the query field at the url of the script, but in order to process this properly I need to do two things first:

  1. strip escape characters
  2. remove document.write(" and "0;

At that point I’m confident that I can do the reformatting I need.

Offline

#192 2013-09-26 16:33:40

etc
Developer
Registered: 2010-11-11
Posts: 3,780
Website

Re: etc_query: all things Textpattern

Hi Dale,

if you import this script from external url and are quite sure about its structure, try this:

<!-- save the script in "some_script" variable -->
<txp:etc_query url="script_url" markup="raw" name="some_script" />

<!-- now clean up and query -->
<txp:etc_query data="{?some_script||trim.preg_replace(/^document\.write\(|\);$/i,,$)}" argsep="," markup="json" />

If it is inside the page itself, you can go the same “save then transform” way, but the optimal solution depends on how many they are, and what has to be extracted.

Offline

#193 2013-09-26 17:34:22

mrdale
Moderator
From: Walla Walla
Registered: 2004-11-19
Posts: 2,203
Website

Re: etc_query: all things Textpattern

Awesome! Did the trick, now I need to do the following. gonna give it a shot myself, just posting here for reference.

The dataset

<div class="display_archive">
  <div class="campaign">09/19/2013 - <a href="#" title="Item 1" target="_blank">Item 1</a></div>
  <div class="campaign">09/12/2013 - <a href="#" title="Item 2" target="_blank">Item 2</a></div>
</div>

In theory (etc check my logic)

  1. match div.campaign /display_archive/campaign/
  2. extract the date from instances of the date /display_archive/campaign/text() into a variable
  3. remove the “ – “ in the variable
  4. use <txp:if_different> to insert an h4 for the month name when it is different from the preceding (converting 1-12 to month names)
  5. echo .campaign

Now for the Implementation

Offline

#194 2013-09-26 18:39:04

etc
Developer
Registered: 2010-11-11
Posts: 3,780
Website

Re: etc_query: all things Textpattern

For some weird good reason, <> get encoded when importing JSON to XML. This seems to work:

<txp:etc_query data="{?some_script||trim.preg_replace(/^document\.write\(|\);$/i,,$).json_decode}"
	argsep="," wraptag="div" class="display_archive" functions="strtotime,date"
	query="//div[@class='campaign']"
>
	<txp:if_different><h4>{date('m', strtotime(translate(text(), ' -', '')))}</h4></txp:if_different>
	{.}
</txp:etc_query>

Edit: added date functions.

Last edited by etc (2013-09-27 10:26:34)

Offline

#195 2013-09-26 21:21:57

mrdale
Moderator
From: Walla Walla
Registered: 2004-11-19
Posts: 2,203
Website

Re: etc_query: all things Textpattern

This is awesome! Thanks… trying very hard to grok this her’s my line by line.

<txp:etc_query data="{?some_script||trim.preg_replace(/^document\.write\(|\);$/i,,$).json_decode}"

{get data from the variable|no default value|transformation chain}

get the variable and apply a transformation chain to it and use that for data (through php functions?)

  1. trim: trims whitespace from start and end of the following
  2. preg_replace: matches the two parts of the unwanted text searching case-insensitive
  3. json_decode decodes the output into an array (why do I need this?)

argsep="," wraptag="div" class="display_archive" functions="strtotime,date" query="//div[@class='campaign']"

  1. argsep: separates the arguments of which part with a comma?
  2. wraptag: and class are txp behaviors
  3. functions: allow the following php functions to be used inside this tag
  4. query: limit the output of this tag to all divs who’s class is “campaign”

<txp:if_different><h4>{date('F', strtotime(translate(text(), ' -', '')))}</h4></txp:if_different>

  1. if_different: behaves as it should ony showing unique values for the inner text returned from the query (inner text of “div.campaign”)
  2. date: returns the date “Month Name” (F) of the enclosed string (make sure to use the code for date not strftime)
  3. strtotime: transforms the text “mm-dd-yyyy” to a timestamp for the enclosed string
  4. translate: this is an Xpath function to do a quick find and replace for unanted text on text()

{.}

Now just return all of the items that are output by the tag’s query from the dataset, rinse, repeat.

Last edited by mrdale (2013-09-27 15:30:09)

Offline

#196 2013-09-27 21:20:36

etc
Developer
Registered: 2010-11-11
Posts: 3,780
Website

Re: etc_query: all things Textpattern

Nice job, Mr. Dale! I’ve got only few comments to add:

<txp:etc_query data="{?some_script||trim.preg_replace(/^document\.write\(|\);$/i,,$).json_decode}"
get the variable and apply a transformation chain to it and use that for data (through php functions?)

Exactly! Actually, the variable could be transformed with pax_grep/rah_replace/rah_function or mere txp:php as well, and then passed as data to etc_query.

json_decode decodes the output into an array (why do I need this?)

You get not an array, but a plain string here, with \" and \/ unescaped. Same result can be achieved with str_replace, but the argument of document.write seems JSON-encoded, so json_decode should do the job fine.

argsep: separates the arguments of which part with a comma?

functions arguments, like in preg_replace(/^document\.write\(|\);$/i,,$). The default argsep is | (pipe), but here we need it in regexp pattern.

functions: allow the following php functions to be used inside this tag

Yes, XPath 1.0 used in PHP DOM has a very limited collection of functions (translate is one of them), but one can complete it with php (string) functions.

query: limit the output of this tag to all divs who’s class is “campaign”

It rather creates a list of nodes you want to use as landmarks, over which etc_query will iterate. The {xpath}’s inside etc_query will be relative to these landmarks ({.} is the node itself, {text()} is the text immediately inside it, and so on). This does not really limit the output, you can display the nodes parent with {..}, for example.

Offline

#197 2013-11-13 11:47:19

gfdesign
Member
From: Argentina
Registered: 2009-04-20
Posts: 401

Re: etc_query: all things Textpattern

Hi Oleg.

Thanks so much for your plugin and explanation about alphabetic list that you put in your site.
I’ve tried to use it in my site but for any reason I can’t. When I put the code, and click on any letter, the articles display but the alphabetic list doesn’t. What could be the problem?

Other questions is, how you would do it if you’d have to do an alphabetic list of professionals separated by professions such us architects, engineers, carpenters. I created a section called “professionals” and each profession has its own category. So, when I want to load a new professional, I create a new article and I assign to the corresponding category. But I wouldn’t know how to use your code for this request. Any idea?

Thanks again in advance.
Regards
Fernando

Offline

#198 2013-11-13 12:18:38

etc
Developer
Registered: 2010-11-11
Posts: 3,780
Website

Re: etc_query: all things Textpattern

Hi Fernando,

gfdesign wrote:

When I put the code, and click on any letter, the articles display but the alphabetic list doesn’t. What could be the problem?

That’s a bit strange, the only explanation I can see right now is that you use another wraptag instead of nav. If so, you should replace {//nav} with {//your_tag} inside the second etc_query. Otherwise, mind providing an url (if it’s online)?

Other questions is, how you would do it if you’d have to do an alphabetic list of professionals separated by professions such us architects, engineers, carpenters. I created a section called “professionals” and each profession has its own category. So, when I want to load a new professional, I create a new article and I assign to the corresponding category. But I wouldn’t know how to use your code for this request. Any idea?

Are you looking for

Architects: A - B - ... - Z
Engineers: A - C - ... - X

or

A: Architects - Engineers
B: Engineers

Both must be doable, let me think about it.
Regards

Offline

#199 2013-11-13 19:54:35

etc
Developer
Registered: 2010-11-11
Posts: 3,780
Website

Re: etc_query: all things Textpattern

Version 1.2.9: just fixes a stupid typo introduced in a recent cleanup. Apologies, and many thanks to Fernando for the report.

Offline

#200 2014-01-14 08:02:48

photonomad
Member
Registered: 2005-09-10
Posts: 287
Website

Re: etc_query: all things Textpattern

Might there be a way/shortcut to get etc_query to automatically store each node from items in a JSON document as a textpattern variables when using etc_query as a container tag? I have couple of date/timestamps that need formatting and other nodes that need to have the html escaped, etc. My programming knowledge is limited to where I can’t figure out how to wrap a {node?} in an smd_wrap tag or other plugin tags without first defining the nodes as txp:variables and this seems to slow the whole thing down a bit. Thanks in advance for any hints or tips!

Offline

Board footer

Powered by FluxBB