Im trying the following:
MainTemplate.ftl
<root>
<#List items as item>
<#include "custom_item.ftl"> [Option 1]
</#List>
<#include "custom_item.ftl"> [Option 2]
</root>
custom_item.ftl
<root>
<name>${name}</name>
</root>
In some files the include is like [Option 1], in others as [Option 2].
To access the ${name} variable i have to use 2 different ways:
- Option 1: ${item.name}
- Option 2: ${name}
Totally understandable, but also my issue. How can i make sure it always works? Like supplying a prefix to the include so its always the same.
For example like:
MainTemplate.ftl
<root>
<#List items as item>
<#include "custom_item.ftl" prefix='item'> [Option 1]
</#List>
<#include "custom_item.ftl"> [Option 2]
</root>
custom_item.ftl
<root>
<# assign prefix = prefix?root>
<name>${prefix.name}</name>
</root>
Which then always would work. My approach clearly doesnt work, does someone has a solution that does work?
Edit: Answer included
MainTemplate.ftl
<root>
<#List listItems as listItem>
<#assign item = listItem>
<#include "custom_item.ftl">
</#List>
<#assign item = .data_model>
<#include "custom_item.ftl">
</root>
custom_item.ftl
<root>
<name>${item.name}</name>
</root>
Always use ${item.name}. In the case when the data-model root itself is the item (is it?), you can do something like <#assign item = .data_model> before the #include.
Related
I am using boost (version 1.70.0) property tree. If I have this XML (no empty lines):
<Root>
<SomeOtherElement>..</SomeOtherElement>
<Collection>
<Item Attr1=".." attr2="" />
<Item Attr1=".." attr2="" />
</Collection>
</Root>
and I extract a node, insert to another (empty) tree:
auto node = pt.get_child("Root.Collection");
ptree new_pt{};
new_pt.put_child("Collection", node);
std::ostringstream os;
write_xml(os, new_pt);
auto xml = os.str();
I will get the output with empty lines, something like this:
<Collection>
<Item Attr1=".." attr2="" />
<Item Attr1=".." attr2="" />
</Collection>
I have tried different things. I can fix it by iterating over Item elements and adding one by one. Then it works, no extra lines. However, if Item element itself has a child element(s), then again, it will add a bunch of empty lines.
I think it's duplicated with this one, or it's just a bug in the property tree.
https://stackoverflow.com/a/6614372/1292791
To read with the trim flag will fix the problem:
pt::read_xml(filename, tree, boost::property_tree::xml_parser::trim_whitespace);
To write with pretty format:
pt::write_xml(os, tree, boost::property_tree::xml_writer_make_settings<std::string>(' ', 1));
I have the following XML structure:
<itemsWithLabels>
<itemLabelValue>
<label>A</label>
<value>a</value>
</itemLabelValue>
<itemLabelValue>
<label>B</label>
<value>b</value>
</itemLabelValue>
<itemLabelValue>
<label>C</label>
<value>c</value>
</itemLabelValue>
</itemsWithLabels>
Using XSL I want to be able to get the value from <value> by knowing the label in <label>.
So my transformation looks like this:
<xsl:value-of select="$content/itemsWithLabels/itemLabelValue/value[#label='A']" />
But clearly something is wrong because I don't have any output.
What am I doing wrong?
Try:
<xsl:value-of select="$content/itemsWithLabels/itemLabelValue[label='A']/value" />
$content/itemsWithLabels/itemLabelValue[label='A'] gets itemLabelValue elements with a label element child having value A. The /value part gets the child value element.
I have the following XML:
<root>
<name1>
<tag1>name1value1</tag1>
<tag2>name1value2</tag2>
</name1>
<name2>
<tag1>name2value1</tag1>
<tag2>name2value2</tag2>
</name2>
</root>
I need to select every name*/tag* values. I tried using * or like this:
<xsl:for-each select="/root/*[starts-with(name(), 'name')]/child::*">
It just doesn't work... Can you please help me?
I am needing a little help with filtering my xml based on a property
I have the XML in the following format:
<?xml version="1.0" encoding="utf-8" ?>
<root id="-1">
<LandingPage id="1067" parentID="1050" level="2"
writerID="0" creatorID="0" nodeType="1066" template="1073"
sortOrder="0" createDate="2013-02-04T14:29:39"
updateDate="2013-02-07T11:08:27" nodeName="About"
urlName="about" writerName="Pete" creatorName="Pete"
path="-1,1050,1067" isDoc="">
<hideInNavigation>0</hideInNavigation>
</LandingPage>
</root>
What I need to do is filter these elements where hideInNavigation = 0
I have tried the following:
[#isDoc and #hideInNavigation ='0']
(I need the #isDoc attribute too) but realised this would only work if hideInNavigation was an attribute of the LandingPage tag so I tried
value['hideInNavigation'='0']
but this didn't seem to do anything either. After much searching for the answer, I haven't come up with anything so was wondering if it is possible
Supposing the current context was the <root> element, you could select the LandingPages with hideInNavigation = 0 with:
LandingPage[hideInNavigation = '0']
If you would share your XSLT, I van give you more specific guidance on how to amend it for this particular case.
And was the #isDoc test in your first example something you wanted? Do you want to filter LandingPages that have an isDoc attribute and a hideInNavigation value of 0?
'hideInNavigation'='0' compares the two strings 'hideInNavigation' and '0', which are guaranteed to be different.
In the context of root, LandingPage[hideInNavigation=0] would match the LandingPage element in your example.
This XPath return all LandingPage with isDoc attribute empty and hideInNavigation element content is '0'
//LandingPage[#isDoc="" and hideInNavigation='0']
<a>
<x/>
<m/>
<y/>
<m/>
</a>
Inside a template that matches 'a', I want to match (first) any 'm's before 'y', and then
separately any 'm's after 'y'.
<xsl:apply-templates select="./m[following::y]"/>
is what I thought of, but I can't get it to work, and, further, I can't see how to prevent the template that matches on 'm' from being applied in the normal flow as well as in the particular place i want to insert the m-related content.
Your template looks OK, but are you sure you want to use following? For example, this template:
<xsl:template match="a">
<a><xsl:apply-templates select="m[following::y]"/></a>
<b><xsl:apply-templates select="m[following-sibling::y]"/></b>
</xsl:template>
...applied to the following XML:
<a>
<x/>
<m>match</m>
<y/>
<m>no match</m>
<nested>
<m>match 2</m>
<y/>
</nested>
</a>
...outputs the following result:
<a>matchno match</a>
<b>match</b>
The first apply-templates matches <m>no match</m> because following includes all nodes that are after the context node in document order, which includes the nested <y/>.
The second template matches only siblings.
For completeness, I'll add the following template, which matches only those <m> nodes whose immediate following sibling is a <y>:
<xsl:template match="a">
<a><xsl:apply-templates select="m[following-sibling::*[1][self::y]]"/></a>
</xsl:template>
This template outputs the following, given the above XML:
<a>match</a>