I have a component in tridion where its metadata design has a field called 'list' which is populated using Categories and Keywords
I used a DWT code to populate items present in the list using the following code using My DWT TBB
<!-- TemplateBeginRepeat name="Metadata.list" -->
<!-- TemplateBeginIf cond="list" -->
##RenderComponentField('list',TemplateRepeatIndex)## ,
<!-- TemplateEndIf -->
<!-- TemplateEndRepeat -->
but Im getting preview as
one,two,three,four,five,
desired output should be like:
one,two,three,four,five
so for this i need to get the maximum count of "TemplateRepeatIndex"
Is there any inbuilt function to check the same.
using Tridion-sp1,2011.
You can solve this with the built in function: CollectionLength.
When you have a multi-valued text field "multiValuedField" you can find the item count using the following expression:
##CollectionLength("Component.Fields.multiValuedField")##
Collection Length receives an expression that is the fully qualified name of an item and a value selector of a package item.
The value returned is a string. When you need to perform an integer comparison or calculation you need to parse the value to an integer:
##parseInt(${CollectionLength("multivalued")})##
This works because the string between ## and ${} is parsed as JScript.
An easy solution would be to switch your logic around.
You can check if TemplateRepeatIndex is 0. If it is not, output the comma in front of the value.
I believe the only way to do this would be to create a TBB that adds the field count as an item in the package. You would then be able to do the following:
<!-- TemplateBeginRepeat name="Metadata.primary_topic" -->
<!-- TemplateBeginIf cond="primary_topic" -->
##RenderComponentField('primary_topic',TemplateRepeatIndex)##<!-- TemplateBeginIf cond="TemplateRepeatIndex < PrimaryTopicCount"--> ,<!-- TemplateEndIf -->
<!-- TemplateEndIf -->
<!-- TemplateEndRepeat -->
Walter solved and explained this topic a few years ago by introducing a custom function.
http://sdltridionworld.com/community/extension_overview/dreamweavercia.aspx
Don't forget to recompile his code for the current version of Tridion.
Update: you can find all built-in functions (and examples of their usage) that Tridion has for use in DWT on this page: http://code.google.com/p/tridion-practice/wiki/BuiltInFunctionsForUseInHtmlTemplates
Related
I have a situation in which an XML document has information in varying depth (according to S1000D schemas), and I'm looking for a generic method to extract correct sentences.
I need to interpret a simple element containing text as one individual part/sentence, and when an element that's containing text contains other elements that in turn contain text, I need to flatten/concatenate it into one string/sentence. The nested elements shall not be visited again if this is done.
Using Pythons lxml library and applying the tostring function works ok if the source XML is pretty-printed, so that I may split the concatenated string into new lines in order to get each sentence. If the source isn't pretty-printed, in one single line, there won't be any newlines to make the split.
I have tried the iter function and applying xpaths to each node, but this often renders other results in Python than what I get when applying the xpath in XMLSpy.
I have started down some of the following paths, and my question is if you have some input on which ones to continue on, or if you have other solutions.
I think I could use XSLT to preprocess the XML file, and then use a simpler Python script to divide the content into a list of sentence for further processing. Using Saxon with Python is now doable, but here I run into problems if the XML source contains entities that I cannot redirect Saxon to resolve (such as & nbsp;). I have no problem parsing files with lxml, so I tend to lean towards a cleaner Python solution.
lxml doesn't seem to have xpath support that can give me all nodes with text that contains one or more children containing text, and all nodes that are simple elements with no parents containing text nodes. Is there way to preprocess the parsed tree so that I can ensure it is pretty printed in memory, so that tostring works the same way for every XML file? Otherwise, my logic gives me one string for a document with no white space, and multiple sentences/strings if the source had been pretty printed. This doesn't feel ok.
What are my options? Use XSLT 1.0 in Python, other parsers to get a better handle on where I am in the tree, ...
Just to reiterate the issue here; I am looking for a generic way to extract text, and the only rules to the XML source are that a sentence may be built from an element with child elements with text, but there won't be additional levels. The other possibility is the simple element, but this one cannot be included in a parent element with text since this is included in the first rule.
Help/thoughts are appreciated.
This is a downright ugly code, a hastily hack with no real thought on form, beauty or finesse. All I am after is one way of doing this in Python. I'll tidy things up when I find a good solution that I want to keep. This is one possible solution so I figured I'd post it to see if someone can be kind enough to show me how to do this instead.
The problems has been to have xpath expressions that could get me all elements with text content, and then to act upon the depending on their context. All my xpath expressions has given me the correct nodes, but also a root, or ancestor that has pulled a more or less complete string at the beginning, so I gave up on those. My xpath functions as they should in XSLT, but not in Python - don't know why...
I had to revert to regex to find nodes that contains strings that are not white space only.
Using lxml with xpath and tostring gives different results depending on how the source XML is formatted, so I had to get around that.
The following formats have been tested:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<subroot>
<a>Intro, element a: <b>Nested b to be included in a, <c>and yet another nested c-element</c> and back to b.</b></a>
<!-- Comment -->
<a>Simple element.</a>
<a>Text with<b> 1st nested b</b>, back in a, <b>and yet another b-element</b>, before ending in a.</a>
</subroot>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<subroot>
<a>Intro, element a: <b>Nested b to be included in a, <c>and yet another nested c-element,
</c> and back to b.</b>
</a>
<!-- Comment -->
<a>Simple element.</a>
<a>Text with<b> 1st nested b</b>, back in a, <b>and yet another b-element</b>, before ending in a.</a>
</subroot>
</root>
<?xml version="1.0" encoding="UTF-8"?><root><subroot><a>Intro, element a: <b>Nested b to be included in a, <c>and yet another nested c-element</c> and back to b.</b></a><!-- Comment --><a>Simple element.</a><a>Text with<b> 1st nested b</b>, back in a, <b>and yet another b-element</b>, before ending in a.</a></subroot></root>
Python code:
dmParser=ET.XMLParser(resolve_entities=False, recover=True)
xml_doc = r'C:/Temp/xml-testdoc.xml'
parsed = ET.parse(xml_doc)
for elem in parsed.xpath("//*[re:match(text(), '\S')]", namespaces={"re": "http://exslt.org/regular-expressions"}):
tmp = elem.xpath("parent::*[re:match(text(), '\S')]", namespaces={"re": "http://exslt.org/regular-expressions"})
if(tmp and tmp[0].text and tmp[0].text.strip()): #Two first checks can yield None, and if there is something check if only white space
continue #If so, discard this node
elif(elem.xpath("./*[re:match(text(), '\S')]", namespaces={"re": "http://exslt.org/regular-expressions"})): #If a child node also contains text
line =re.sub(r'\s+', ' ',ET.tostring(elem, encoding='unicode', method='text').strip()) #Replace all non wanted whitespace
if(line):
print(line)
else: #Simple element
print(elem.text.strip())
Always yields:
Intro, element a: Nested b to be included in a, and yet another nested c-element, and back to b.
Simple element.
Text with 1st nested b, back in a, and yet another b-element, before ending in a.
The JOOQ Java code generation tools uses regular expressions defined in the includes and excludes elements to control what is generated. I cant find an explanation of what the schema structure is that these expressions are run against.
I want to have the ability to exclude specific databases in the server as well as tables by prefix or specifically.
Simple examples:
Given a SQL server with two DBs 'A' and 'B', how do I instruct JOOQ to only generate for tables in DB 'A'?
How do in instruct JOOQ to only generate for tables starting with the prefix "qtbl"?
It would be great if there were some example use cases available showing some simple common configurations.
The jOOQ manual section about includes and excludes, as well as a few other sections that explain the code generator's usage of regular expressions to match identifier establishes that the code generator will always try to:
Match fully qualified identifiers
Match unqualified identifiers
Or, if you're using jOOQ 3.12+ and did not turn off <regexMatchesPartialQualification/>:
Match partially qualified identifiers (see #7947)
For example:
<excludes>
(?i: # Using case insensitive regex for the example
database_prefix.*?\. # Match a catalog prefix prior to the qualifying "."
.*?\. # You don't seem to care about schema names, so match them all
table_prefix.*? # Match a table prefix at the end of the identifier
)
</excludes>
In addition to the above, if you want to exclude specific databases ("catalogs") from being generated without pattern matching, you'll get even better results if you specify your <inputCatalog>A</inputCatalog>. See also the manual's section about schema mapping.
Benefits include a much faster code generation, because only that catalog will be searched for objects to generate, prior to excluding them again using regular expressions. So, your configuration could be this:
<!-- Include only database A -->
<inputCatalog>A</inputCatalog>
<!-- Include only tables with this (unqualified) prefix -->
<includes>qtbl.*</includes>
I am using a simple looping plugin so that my template looks like this:
{exp:loop_plus start="1" end="4" increment="1"}
<h3>{slide_{index}_title}</h3>
{/exp:loop_plus}
However, I am ending up with the following output:
<h3>{slide_1_title}</h3>
<h3>{slide_2_title}</h3>
<h3>{slide_3_title}</h3>
<h3>{slide_4_title}</h3>
Is there any way I can have dynamic variable names like this? I am not looking for alternative methods for building a slider, I simply would like to know if the dynamic variable names like this is possible. Thanks!
I'm assuming that Loop Plus (http://devot-ee.com/add-ons/loop-plus) sets the {index} part, so the question is what is defining {slide_1_title}...?
Assuming you have an entry field or variable with this defined, what you have is correct, but if it's not working, it means there's a parsing order issue.
Let's assume the code you supplied is wrapped in a {exp:channel:entries} tag pair, what happens is EE will try to parse the variable first, so will see: {slide_{index}_title} which doesn't exist. The {exp:loop_plus} add-on will then parse it, converting it to {slide_1_title} (but to late as channel:entries has already tried to parse it), which is what is finally output to the template.
So what you want to ensure is that EE parses {exp:loop_plus} before {exp:channel:entries}, do this using parse="inward" tag:
{exp:loop_plus start="1" end="4" increment="1" parse="inward"}
<h3>{slide_{index}_title}</h3>
{/exp:loop_plus}
This is a global EE parameter that EE uses to control parse order - you won't find it documented under the specific add-on. By adding the parameter, it means this child tag will get parsed before it's parent.
One way you could do it is to declare a preload_replace variable in your template and use it in your custom field name.
So something like:
{preload_replace:my_var_prefix="whatever"}
And then in your loop, you could then use:
{slide_{my_var_prefix}_title}
I have an input text that is mapped to a Long property.
private Long length;
<h:inputText value="#{bean.length}" />
When I enter non-digits in that input text, I get the following conversion error:
myForm:myField: 'someText' must be a number consisting of one or more digits.
I was wondering how to customize this message to:
length must be a number greater than zero.
Either use the input component's converterMessage attribute:
<h:inputText converterMessage="length must be a number greater than zero" />
(and don't forget to use <f:validateLongRange> to prevent users being able to enter negative values and supply a validatorMessage!)
Or create a properties file in the classpath which overrides the default message of the builtin JSF LongConverter:
javax.faces.converter.LongConverter.LONG = length must be a number greater than zero
and is been registered as message bundle in faces-config.xml:
<application>
<message-bundle>com.example.CustomMessages</message-bundle>
</application>
The above example assumes that the file name is CustomMessages.properties and is been placed in com.example package. You can name and place it wherever you want.
You can find an overview of all message keys like javax.faces.converter.LongConverter.LONG and their default values in chapter 2.5.2.4 of the JSF specification which is also copypasted in this answer.
How to obtain document library name from the URL cqwp. For example,
http:///sites/site1/DocLib/Forms/AllItems.aspx
I know there is substring function with xsl
<xsl:param name="DocLibName">
select=substring(url) or whatever the code should be
</xsl:param>
The following code will give you the name of your document library from the URL you posted (or from any view in your document library)
String pattern = ".*/(?<listStaticName>.+)/[^\\.]+\\.aspx";
Regex regex = new Regex(pattern);
MatchCollection matches = regex.Matches(DefaultViewUrl);
String listStaticName = matches[0].Groups["listStaticName"].ToString();
You can use the method described in this article to call .NET code from XSL
Using the standard substring(string, int, int) function won't get you very far because I expect that the length of the document library name is unknown.
However, there are two functions that you can use in concert, substring-after(string, string) and substring-before(string, string). As long as your site names aren't "Forms", you can retrieve a partial string using substring-before([URL], "/Forms"). For the rest... it'll still be troublesome if you don't have immediate access to the site's name, but even removing that option it's still much easier than complex calculations in URL length. You'd basically have to continually perform substring-after([string], "/") until you pop off the last slash.
Some good Links.
http://msdn.microsoft.com/en-us/library/dd583143(office.11).aspx
Add these two line
<xsl:variable name="DocLibName" select="substring-before(substring-after($PageUrl, '/Forms/'), '/')" />
<xsl:param name="PageUrl"/>
set VIEWFLAG=1 (it should be in the properties windows)
Find this line and modify if you want Filter the webpart list
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row" />
Change it to following
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[(#CustomerNo=$DocLibName)]"/>
You can use this to display
<xsl:value-of select="$DocLibName"> <br/>
<xsl:value-of select="$PageUrl"/><br/>