Where does the inconsistency in behaviour of Mediawiki templates come from? - mediawiki

This question pertains to the inconsistent behaviour of Mediawiki syntax and its templates and parser functions.
When placed directly in a wiki page, both these snippets work as expected:
{{#ifeq:{{{1|}}}|{{{2}}}|{{{1}}}}}
and
{{#ifeq:{{{1|{{FULLPAGENAME}}}}}|{{NAMESPACE:{{{1|{{FULLPAGENAME}}}}}}}:{{ROOTPAGENAME:{{{1|{{FULLPAGENAME}}}}}}}|{{{1|{{FULLPAGENAME}}}}}}}
The first snippet is simple. The second outputs the full name of the page, but only if it is not a sub-page.
However, when each snippet is placed in a template, let's say the first in Template:IsEqual, and the second in Template:IsRootPage, both of which are then included in some page, such as the output of each is the subject of an #if test, the first continues to behave as expected, while the second always yields the string not empty section of the #if statement.
So:
{{#if:{{IsEqual|A|B}}|equal|unequal}} will output "unequal"
while:
{{#if:{{IsRootPage}}|root|non-root}} will always output "root", even if placed in a subpage or if the name of a non-top-page is passed as a parameter to Template:IsRootPage, driving the template to return nothing.
According to the documentation of #if:
This function evaluates a test string and determines whether or not it
is empty. A test string containing only white space is considered to
be empty.
Moreover, the inconsistent behaviour persists for Template:IsRootPage even when it is amended to return an empty string when the #ifeq test fails, by introducing a fourth empty parameter to the #ifeq in the template, i.e by adding a third | followed by nothing/space.
It seems that something happens in between the output of the template and the #if parser function.
Is there a known explanation for this discrepancy in behaviour?
Is there some syntax hack to make it work as expected?
Or am I missing something that's otherwise obvious?
Edit: This behaviour is witnessed in Mediawiki 1.35.5

Your sample template does not return an empty string when the page has sub pages. It returns <nowiki/> for which {{#if:<nowiki/>|yes|no}} properly returns yes.
If you remove the <nowiki/>, you'll get the behavior you want.

Related

How can I store an XPath as a variable in Python Selenium?

I want to be able to select text on a website, store it, and then turn that stored information into a variable. More specifically as seen in the picutre below, my goal is for the selected name, in this case, John J. John, somehow be copied, turned into a variable, and then printed, all without emulating any key binds.
HTML Inspect element photo
The code I have tried to use to get the information is this:
selectedName = browser.find_element_by_xpath('//*[#id="sign_in_box"]/div/div[2]/div/div[1]/div').get_attribute("div")
print (selectedName)
The return I am getting is this:
None
I know that the problem almost definetly lies somewhere in the path, but I can't figure it out.
Assuming your xpath is correct, you should put .text instead of .get_attribute("div") since it will not return the text you want, but the div itself.
How to get text with Selenium WebDriver in Python
Try
selectedName = browser.find_element_by_xpath('//*[#id="sign_in_box"]/div/div[2]/div/div[1]/div').text

How can I substitute a magic word only when transcluding template without using #invoke?

I'm trying to make a template that shows the time it was placed. I tried this:
This is a template ({{<includeonly>subst:</includeonly>CURRENTTIMESTAMP}})
but when transcluded it would show up as This is a template ({{subst:CURRENTTIMESTAMP}}) instead of substituting the timestamp. I then tried
This is a template ({{{{{|safesubst:}}}CURRENTTIMESTAMP}})
but that didn't substitute it; the timestamp would keep updating. Next, I tried
This is a template ({{<includeonly>{{{|safesubst:}}}</includeonly>CURRENTTIMESTAMP}})
but no dice.
I know it's possible with {{#invoke:}} but I don't have that option. Could someone help me out?
Consider how templates are stored. If you recursively subst the template, the contents of the template are stored in the wikitext of the including page, with CURRENTTIMESTAMP replaced with the actual timestamp. If you do not subst the template, the wikitext will only contain {{MyTemplate}}, and the timestamp of the edit is not stored anywhere; when the the parser renders the article and encounters CURRENTTIMESTAMP, it will just use the current timestamp. There is no way around that, #invoke or not.
What you can do is make the timestamp into a parameter, so in the including page you would write {{MyTemplate|{{subst:CURRENTTIMESTAMP}}}} and then the timestamp gets stored in the page. You can create a wrapper template with that exact content so that users only have to type {{subst:MyTemplateWrapper}} which is a bit easier. You can even make the template show an error / add an error category when used without substing, although that's a bit more involved.

Hide the text input field portion in a form's GET query url when the value is an empty string

e.g.: http://127.0.0.1:8000/database/?reference_doi=&submit=Submit
I know It appears to be an html standard, but is there a tag to switch it, so that the empty text input string does not appear in the query url?
Or alternatively, since I'm using Django, I tried doing the following in my view.
request_get_copy = request.GET.copy()
for key, value in request_get_copy.items():
if not value or key == 'submit':
request_get_copy.pop(key)
request.GET = request_get_copy
request.META['QUERY_STRING'] = request_get_copy.urlencode()
I displayed request.GET and request.META['QUERY_STRING'] in the actual page through my template, and several methods that request object has, and they all gave successfully "corrected" values, like http://127.0.0.1:8000/database/ But since the GET request first goes through the browser, the displayed url still contains empty string value portions. Is there anything I can do?
The easiest thing you could do is to issue a redirect to your fixed URL:
fixed_url = request_get_copy.urlencode()
return redirect(fixed_url)
Even better if you do that only if it actually changed, and before any DB access or heavy work.
This means an additional GET, but gives you the result you want, and I guess that's more valuable to you :)
If Javascript is an option, you could also do this changes before the submit actually happens, it's a tad more convoluted but will avoid the extra request.
Edit: Just to be clear, there's no way to "turn it off", you could say this is how HTTP and browsers work :)

How do I determine the current pages document type in umbraco?

I have what I feel is a very simple question about Umbraco, but one that has as of yet no apparent answer.
I have a razor template, standard stuff, with # displaying variables and some inline C# code.
At one point in the template I use:
#Umbraco.RenderMacro("myCustomMacro");
no problems there, everything works as expected.
Now, this macro is inserted on every page (it's in the master template) but I have a page property that allows the content authors to turn it on and off via a check box in the page properties, again so far so good everything works perfectly.
However I now find that for a certain "document type" this component MUST be displayed, so I've been trying to find a way to perform that check.
Now in my mind, this should be as simple as doing something like this:
#{
if(CurrentPage.documentType == "someDocTypeAliasHere")
{
//Render the macro
}
else
{
// Render the macro only if the tick box is checked
}
}
as I say, this is (or I believe it should be anyway) a very simple operation, but one that so far does not seem to have a result.
What Have I tried so far?
Well apart from reading every page on our-umbraco that mentions anything to do with razor & the #CurrentPage variable, Iv'e been through the razor properties cheat sheet, and tried what would appear to be the most common properties including (In no specific order):
#CurrentPage.NodeTypeAlias
#CurrentPage.NodeType
#CurrentPage.ContentType
#CurrentPage.DocumentType
and various letter case combinations of those, plus some others that looked like they might fit the bill.
Consistently the properties either don't exist or are empty so have no useable information in them to help determine the result.
So now after a couple of days of going round in circles, and not getting anywhere I find myself here..
(Please note: this is not a search the XSLT question, or iterate a child collection or anything like that, so any requests to post XSLT, Macros, Page templates or anything like that will be refused, all I need to do is find a way to determine the Document Type of the current page being rendered.)
Cheers
Shawty
PS: Forgot to mention, I'm using
umbraco v 4.11.8 (Assembly version: 1.0.4869.17899)
Just in case anyone asks.
In Umbraco 7 use currentPageNode.DocumentTypeAlias
In Umbraco 7.1 I use: #if (#CurrentPage.DocumentTypeAlias == "NewsItem")
think you do actually need to create a node each time when you are on the page to access the pages properties like nodetypealias and stuff, try this i have the same kind of functionality on my site, http://rdmonline.co.uk/ but in the side menu where depending on the page/section it shows a diff menu links.
#{
var currentPageID = Model.Id;
var currentPageNode = Library.NodeById(currentPageID);
if (currentPageNode.NodeTypeAlias == "someDocTypeAliasHere")
{
//Render the macro
}
else
{
// Render the macro only if the tick box is checked
}
}
Let me know if this works for you.
This is a bit unrelated to this post, but searching Google brought me to this post, so I thought I'd share in case anoyne else is dealing with this issue: In Umbraco 7, to get all content in the site for a specific type:
var articles = CurrentPage.AncestorOrSelf(1).Descendants()
.Where("DocumentTypeAlias == \"BlogPost\"").OrderBy("CreateDate desc");
If your razor view inherits from Umbraco.Web.Mvc.UmbracoViewPage, you could also use UmbracoHelper:
#if (UmbracoHelper.AssignedContentItem.DocumentTypeAlias.Equals("NewsItem")) { ... }
Querying for a specific DocumentType is also easy:
UmbracoHelper.AssignedContentItem.Descendants("NewsItem")
This code will recursively return the list of IPublishedContent nodes.
If you wish to use this list with your specific DocumentType information, these items would have to be mapped to the specific type. Other than that, IPublishedContent gives you the basic information for the nodes.
I've later saw that you have been using an older version of Umbraco. :)
This implementation is only for v7.

How can I remove or escape new line-carriage returns within an XML string in XSL?

I've got an ASP multiline textbox that saves user defined text to a database. When I retrieve the data, I serialize it into xml and then run it through an XSL transform to output my HTML.
Within my transform, I am passing the textbox defined data into a javascript function via an onclick event of an element.
The problem I'm running into...when a user enters a carriage return into the textbox and saves it to the database, a javascript error is generated on page load.
I'm using .NET's XslCompiledTransform to do the transform. There is a property on XmlDocument called PreserveWhiteSpace, default is false, that can be set to strip out white space in the XML. This solves the problem of not allowing a user to enter breaking text, however, the client wants to preserve the formatting of the text that they enter if at all possible.
From what I know, .NET XslCompiledTransform transforms carriage returns-new line into
. I believe these are the characters that are breaking the javascript.
My first thought was to strip out the carriage returns within the xsl prior to passing the string into the javascript function, but I've not been able to figure out what characters to "search" the string for.
I guess another question is what characters get stored in SQL for carriage returns from within an ASP.NET textbox control?
Looking directly at the data in the database, SQL seems to display the character as "non-displayable" characters or (2 empty boxes).
Has anyone had any experience with this type of thing?
I was able to do this in the code behind to get my desired results:
using (StringWriter sWriter = new StringWriter())
{
xTrans.Transform(xDoc, xslArgs, sWriter);
return sWriter.ToString().Replace("
", "\\r\\n");
}
One other thing that I've stumbled across...
Initially, I wanted to find a solution to this problem that did not require a "compiled" code change, ie. a way to do this within xsl aka "a short term fix".
I tried this first and was not successful...
<xsl:variable name="comment" select="normalize-space(.\Comment)" />
This essentially did nothing and I was still receiving the javascript error.
Eventually, I tried this...
<div onclick="Show('{normalize-space($comment)}'"></div>
The second actually worked in stripping out the white space, thus, the javascript error was avoided. This wasn't a complete solution for my requirements because it only solved the issue of the javascript error, however, it would effectively prevent the user from "breaking" the page.
For that reason, it could suffice as a short term solution.