Using the <#ftl> directive in a freemarker template - spring

I'm trying to have Freemarker parse my template files as UTF-8, but it seems to be always parsing them as Cp1252.
2013-07-30 00:00:00.984 DEBUG freemarker.cache:? Could not find template in cache, creating new one; id=["myFile.ftl"["es_MX",Cp1252,parsed] ]
I searched and found that adding the FTL directive allows me to specify the encoding.
I added it to the template file (saved in UTF-8 with BOM in Notepad++) like so:
<#ftl encoding="UTF-8">
Estimado Usuario,
Testing this content!
<#/ftl>
But get this in the log.
MessageTemplateException [message=Unable to process template due to Encountered "<#ftl " at line 1, column 4 in myFile.ftl.
Was expecting one of:
<EOF>
<ATTEMPT> ...
<IF> ...
<LIST> ...
<FOREACH> ...
<SWITCH> ...
<ASSIGN> ...
<GLOBALASSIGN> ...
<LOCALASSIGN> ...
<_INCLUDE> ...
<IMPORT> ...
<FUNCTION> ...
<MACRO> ...
<TRANSFORM> ...
<VISIT> ...
<STOP> ...
<RETURN> ...
<CALL> ...
<SETTING> ...
<COMPRESS> ...
<COMMENT> ...
<TERSE_COMMENT> ...
<NOPARSE> ...
<BREAK> ...
<SIMPLE_RETURN> ...
<HALT> ...
<FLUSH> ...
<TRIM> ...
<LTRIM> ...
<RTRIM> ...
<NOTRIM> ...
<SIMPLE_NESTED> ...
<NESTED> ...
<SIMPLE_RECURSE> ...
<RECURSE> ...
<FALLBACK> ...
<ESCAPE> ...
<NOESCAPE> ...
<UNIFIED_CALL> ...
<WHITESPACE> ...
<PRINTABLE_CHARS> ...
<FALSE_ALERT> ...
"${" ...
"#{" ...
with inputs of {loginUrl=testURL} in myFile.ftl with locale es_MX, code=SUCCESS, arguments=[]]
Maybe I'm not doing this right?

Don't use BOM. Also don't use </#ftl>, there's only <#ftl>. But most importantly, if most of your templates are in UTF-8, just set the default encoding of FreeMarker to UTF-8 (in Spring, something like <bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">...<property name="freemarkerSettings">...<props>...<prop key="default_encoding">UTF-8</prop>), so your don't need to use #ftl because of this.

I had the same problem today and finally found a way to use the <#ftl> directive, so in case the same thing happens to anyone :
My problem was that I didn't put the <#ftl> directive on top of my template. As soon as I put it on the first line of my template, everything worked like a charm.

Related

How to filter gradle when copying files? If token starts with "Tel-" and ends with "-Tel" replace token with V2

Gradle Script
copy {
from 'src/com/comcast/telescope/Telescope.java'
into 'dist/com/comcast/telescope'
include '**/*.java'
}
Ant script
<copy file="${src.dir}/com/comcast/telescope/Telescope.java" toFile="${dist.dir}/com/comcast/telescope/Telescope.java">
<filterset begintoken="Tel-" endtoken="-Tel">
<filter token="IntVer" value="${Interface-Version}" />
</filterset>
I got the top part to copy the file, but I'm stuck on filtering the file when copying. Can someone help me?
You would need to add a call to filter in your CopySpec.
Based on the original Ant script, you need:
import org.apache.tools.ant.filters.ReplaceTokens
copy {
from 'src/com/comcast/telescope/Telescope.java'
into 'dist/com/comcast/telescope'
include '**/*.java'
filter(ReplaceTokens, beginToken:'Tel-', endToken:'-Tel', tokens: [IntVer: interfaceVersion])
}
This uses ReplaceTokens to replace the literal text Tel-IntVer-Tel in Telescope.java with the value of interfaceVersion as it is copied from src/com/comcast/telescope to dist/com/comcast/telescope
Please note that in my example you will need to set the interfaceVersion property somewhere, like in gradle.properties or in an ext block. Lastly, I believe that the include is unnecessary, as only one file is being copied, yielding:
import org.apache.tools.ant.filters.ReplaceTokens
copy {
from 'src/com/comcast/telescope/Telescope.java'
into 'dist/com/comcast/telescope'
filter(ReplaceTokens, beginToken:'Tel-', endToken:'-Tel', tokens: [IntVer: interfaceVersion])
}

Custom TemplateExceptionHandler

I need to change the FreeMarker behavior about processing template&data in case some data are missing.
In missing case I need to let the template unchanged and continue in processing.
Example:
Template:
...
var1 = ${var1}
var2 = ${var2}
...
Data:
var1 = Hello
I need Result after processing:
...
var1 = Hello
var2 = ${var2}
...
My solution is:
class MyTemplateExceptionHandler implements TemplateExceptionHandler {
public void handleTemplateException(TemplateException te, Environment env, java.io.Writer out)
throws TemplateException {
try {
//2nd word on 2nd row is name of missing variable :(
String missingVariable = te.getMessageWithoutStackTop().split("\n")[1].split(" ")[1];
out.write("${" + missingVariable + "}");
} catch (IOException e) {
throw new TemplateException("Failed to print error message. Cause: " + e, env);
}
} }
and using:
...
Configuration cfg = new Configuration();
cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());
...
My solution works, but I am not satisfied because of:
1) getting missing variable in handleTemplateException() is horrible. Does exist better way how to get a name of missing variable?
2) Even if I have my own TemplateExceptionHandler, FreeMarker writes enough information to output. Can I change it?
Example output for missing variable "environment_name":
22.10.2014 9:01:55 freemarker.log._JDK14LoggerFactory$JDK14Logger error
SEVERE: Error executing FreeMarker template
FreeMarker template error:
The following has evaluated to null or missing:
==> environment_name [in template "Osb-PrepareAndDeploy.ftl" at line 33, column 33]
Tip: If the failing expression is known to be legally null/missing, either specify a default value with myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthessis: (myOptionVar.foo)!myDefault, (myOptionVar.foo)??
The failing instruction (FTL stack trace):
----------
==> ${environment_name} [in template "Osb-PrepareAndDeploy.ftl" at line 33, column 31]
----------
Java stack trace (for programmers):
----------
freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:98)
at freemarker.core.EvalUtil.coerceModelToString(EvalUtil.java:382)
at freemarker.core.Expression.evalAndCoerceToString(Expression.java:115)
at freemarker.core.DollarVariable.accept(DollarVariable.java:76)
at freemarker.core.Environment.visit(Environment.java:265)
at freemarker.core.MixedContent.accept(MixedContent.java:93)
at freemarker.core.Environment.visit(Environment.java:265)
at freemarker.core.Environment.process(Environment.java:243)
at freemarker.template.Template.process(Template.java:277)
at net.homecredit.scm.jenkinsTool.countrySettings.Country.createJobs(Country.java:282)
at net.homecredit.scm.jenkinsTool.Start.main(Start.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
You can't prevent the exception from being logged. TemplateExceptionHandler doesn't mean to make non-error from an error, it just lets you decide what to do after the error has happened. Like, you want to print an error page or something. In extreme case, you may want to continue page rendering after printing some error indicator, but that's still an error that need to be fixed.
Maybe it would help if you tell why do you need this. Maybe the solution isn't TemplateExceptionHandler-s.
As of more intelligent exception processing, first, in the handler you should check if the exception is a InvalidReferenceException, becaue I guess you don't want to deal with others. Then, with getBlamedExpressionString() (requires FreeMarker 2.3.21) you could get part of what you want to print to the output. It's only part of that, because if ${x + 1} fails because x is undefined, it will only return "x", not "x + 1".

Mule expression in logger component not valid xpath

I have an xml like this:
<order>
<orderheader>
<orderissuedate>1/11/2013</orderissuedate>
</orderheader>
</order>
in the mule logger component set with INFO, i have a mule expression that tries to print out the orderissuedate 1/11/2013.
i use the expression:
[xpath('/order/orderheader//orderissuedate')] which didn't work.
i also tried: #[xpath('/order/orderheader/orderissuedate/text()').text] that didnt work also.
can someone tell me what the correct xpath expression is. i get this error message:
java.lang.RuntimeException: org.mule.api.MuleRuntimeException: Failed to evaluate XPath expression: "/Order/OrderHeader/OrderIssueDate/text()"
I've tested these xpath expressions using online xpath checkers, and they seem to work. thanks for your help.
Here is the original xml:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Order>
<Order
xmlns:core="rrn:org.xcbl:schemas/xcbl/v4_0/core/core.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<OrderHeader>
<OrderNumber>
<BuyerOrderNumber>111111</BuyerOrderNumber>
</OrderNumber>
<OrderIssueDate>2013-06-28T08:40:12</OrderIssueDate>
<OrderReferences>
<AccountCode>
<core:RefNum></core:RefNum>
</AccountCode>
</OrderReferences>
</OrderHeader>
</Order>
and the error output from mule:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
java.lang.RuntimeException: org.mule.api.MuleRuntimeException: Failed to evaluate XPath expression: "/OrderIssueDate"
at org.mule.module.xml.el.XPathFunction.call(XPathFunction.java:50)
at org.mule.el.mvel.MVELFunctionAdaptor.call(MVELFunctionAdaptor.java:38)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:1011)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:987)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:377)
at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:143)
at org.mvel2.ast.ASTNode.optimize(ASTNode.java:159)
at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:115)
at org.mvel2.MVELRuntime.execute(MVELRuntime.java:85)
at org.mvel2.compiler.CompiledExpression.getDirectValue(CompiledExpression.java:123)
at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:119)
at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:113)
at org.mvel2.MVEL.executeExpression(MVEL.java:942)
at org.mule.el.mvel.MVELExpressionExecutor.execute(MVELExpressionExecutor.java:50)
at org.mule.el.mvel.MVELExpressionLanguage.evaluateInternal(MVELExpressionLanguage.java:214)
at org.mule.el.mvel.MVELExpressionLanguage.evaluate(MVELExpressionLanguage.java:163)
at org.mule.el.mvel.MVELExpressionLanguage.evaluate(MVELExpressionLanguage.java:142)
at org.mule.expression.DefaultExpressionManager.evaluate(DefaultExpressionManager.java:220)
at org.mule.expression.DefaultExpressionManager$2.match(DefaultExpressionManager.java:481)
at org.mule.util.TemplateParser.parse(TemplateParser.java:153)
at org.mule.util.TemplateParser.parse(TemplateParser.java:130)
at org.mule.expression.DefaultExpressionManager.parse(DefaultExpressionManager.java:477)
at org.mule.expression.DefaultExpressionManager.parse(DefaultExpressionManager.java:436)
at org.mule.api.processor.LoggerMessageProcessor.log(LoggerMessageProcessor.java:89)
at org.mule.api.processor.LoggerMessageProcessor.process(LoggerMessageProcessor.java:71)
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:27)
at org.mule.execution.MessageProcessorNotificationExecutionInterceptor.execute(MessageProcessorNotificationExecutionInterceptor.java:61)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:47)
at org.mule.processor.chain.DefaultMessageProcessorChain.doProcess(DefaultMessageProcessorChain.java:95)
at org.mule.processor.chain.AbstractMessageProcessorChain.process(AbstractMessageProcessorChain.java:70)
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:27)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:47)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:106)
at com.mulesoft.mule.module.datamapper.processors.DataMapperMessageProcessor.process(DataMapperMessageProcessor.java:132)
at org.mule.execution.ExceptionToMessagingExceptionExecutionInterceptor.execute(ExceptionToMessagingExceptionExecutionInterceptor.java:27)
at org.mule.execution.MessageProcessorNotificationExecutionInterceptor.execute(MessageProcessorNotificationExecutionInterceptor.java:61)
at org.mule.execution.MessageProcessorExecutionTemplate.execute(MessageProcessorExecutionTemplate.java:47)
at org.mule.processor.AbstractInterceptingMessageProcessorBase.processNext(AbstractInterceptingMessageProcessorBase.java:106)
at org.mule.interceptor.AbstractEnvelopeInterceptor.process(AbstractEnvelopeInterceptor.java:55)
at org.mule.processor.AsyncInterceptingMessageProcessor.processNextTimed(AsyncInterceptingMessageProcessor.java:122)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker$1.process(AsyncInterceptingMessageProcessor.java:192)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker$1.process(AsyncInterceptingMessageProcessor.java:185)
at org.mule.execution.ExecuteCallbackInterceptor.execute(ExecuteCallbackInterceptor.java:20)
at org.mule.execution.HandleExceptionInterceptor.execute(HandleExceptionInterceptor.java:34)
at org.mule.execution.HandleExceptionInterceptor.execute(HandleExceptionInterceptor.java:18)
at org.mule.execution.BeginAndResolveTransactionInterceptor.execute(BeginAndResolveTransactionInterceptor.java:58)
at org.mule.execution.ResolvePreviousTransactionInterceptor.execute(ResolvePreviousTransactionInterceptor.java:48)
at org.mule.execution.SuspendXaTransactionInterceptor.execute(SuspendXaTransactionInterceptor.java:54)
at org.mule.execution.ValidateTransactionalStateInterceptor.execute(ValidateTransactionalStateInterceptor.java:44)
at org.mule.execution.IsolateCurrentTransactionInterceptor.execute(IsolateCurrentTransactionInterceptor.java:44)
at org.mule.execution.ExternalTransactionInterceptor.execute(ExternalTransactionInterceptor.java:52)
at org.mule.execution.RethrowExceptionInterceptor.execute(RethrowExceptionInterceptor.java:32)
at org.mule.execution.RethrowExceptionInterceptor.execute(RethrowExceptionInterceptor.java:17)
at org.mule.execution.TransactionalErrorHandlingExecutionTemplate.execute(TransactionalErrorHandlingExecutionTemplate.java:113)
at org.mule.execution.TransactionalErrorHandlingExecutionTemplate.execute(TransactionalErrorHandlingExecutionTemplate.java:34)
at org.mule.processor.AsyncInterceptingMessageProcessor$AsyncMessageProcessorWorker.doRun(AsyncInterceptingMessageProcessor.java:184)
at org.mule.work.AbstractMuleEventWork.run(AbstractMuleEventWork.java:43)
at org.mule.work.WorkerContext.run(WorkerContext.java:311)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.mule.api.MuleRuntimeException: Failed to evaluate XPath expression: "/OrderIssueDate"
at org.mule.module.xml.expression.AbstractXPathExpressionEvaluator.evaluate(AbstractXPathExpressionEvaluator.java:144)
at org.mule.expression.DefaultExpressionManager.evaluate(DefaultExpressionManager.java:311)
at org.mule.expression.DefaultExpressionManager.evaluate(DefaultExpressionManager.java:230)
at org.mule.expression.DefaultExpressionManager.evaluate(DefaultExpressionManager.java:186)
at org.mule.module.xml.el.XPathFunction.call(XPathFunction.java:43)
... 60 more
Caused by: org.mule.api.transformer.TransformerException: Could not find a transformer to transform "SimpleDataType{type=java.util.LinkedHashMap, mimeType='*/*'}" to "SimpleDataType{type=org.dom4j.Document, mimeType='*/*'}".
at org.mule.registry.MuleRegistryHelper.lookupTransformer(MuleRegistryHelper.java:252)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:355)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:313)
at org.mule.module.xml.expression.AbstractXPathExpressionEvaluator.getPayloadForXPath(AbstractXPathExpressionEvaluator.java:154)
at org.mule.module.xml.expression.AbstractXPathExpressionEvaluator.evaluate(AbstractXPathExpressionEvaluator.java:115)
... 64 more
ERROR 2013-08-26 00:40:49,893 [[mule_egc2].EGC_FlowFlow1.stage1.02] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : Could not find a transformer to transform "SimpleDataType{type=java.util.LinkedHashMap, mimeType='*/*'}" to "SimpleDataType{type=org.dom4j.Document, mimeType='*/*'}".
Code : MULE_ERROR-236
--------------------------------------------------------------------------------
Exception stack is:
1. Could not find a transformer to transform "SimpleDataType{type=java.util.LinkedHashMap, mimeType='*/*'}" to "SimpleDataType{type=org.dom4j.Document, mimeType='*/*'}". (org.mule.api.transformer.TransformerException)
org.mule.registry.MuleRegistryHelper:252 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transformer/TransformerException.html)
--------------------------------------------------------------------------------
Root Exception stack trace:
org.mule.api.transformer.TransformerException: Could not find a transformer to transform "SimpleDataType{type=java.util.LinkedHashMap, mimeType='*/*'}" to "SimpleDataType{type=org.dom4j.Document, mimeType='*/*'}".
at org.mule.registry.MuleRegistryHelper.lookupTransformer(MuleRegistryHelper.java:252)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:355)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:313)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
Use this:
<logger message="OrderIssueDate is #[xpath('//Order/OrderHeader/OrderIssueDate').text]" level="INFO" />
Make sure that to use the case correctly for your XML elements hierarchy. You have order in top XML while Order in lower one and so on
the xpath expression that would work according to me is #[xpath://orderissuedate] To print using the logger you should use something like <logger message="#[xpath://orderissuedate]" level="INFO"/>
From the conversation on one of the answers the following solutions hould work.
<logger message="Value of Order Issue Date #[xpath('//OrderIssueDate').text]" level="INFO" />
It would be better if the DTD of the Order is also provided.
Your original XML seems to have namespace :-
xmlns:core="rrn:org.xcbl:schemas/xcbl/v4_0/core/core.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
So, if you need to extract the value using Xpath from your original XML, you need Mule namespace manger :- https://developer.mulesoft.com/docs/display/current/XML+Namespaces
Other than that if you want to extract the value from your XML you shown above, you can use the Mules latest Xpath3 available right now from Mule version 3.6 which is easy to use :- https://developer.mulesoft.com/docs/display/current/XPath
Hope it helps you :)
You can use the mule latest xpath3 like this if you are getting namespaces
[xpath3('//*:orderissuedate/text()')]
Try this, it may help:
#[xpath3('//order/orderheader/orderissuedate/text()')]

Xmllint using XSD+XMLCatalog cannot find uri

I am trying to use xmllint with an XSD file that uses one xs:import without the #schemaLocation attrib set. (In OxygenXMLEditor this setup is working fine)
XSD relevant section:
...
<!-- this one is the trouble -->
<xs:import namespace="http://www.w3.org/1999/xhtml" />
<!-- this one is resolved fine -->
<xs:import namespace="http://www.idpf.org/2007/ops" schemaLocation="conf/b.xsd"/>
...
Given this XML Catalog file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog PUBLIC "-//OASIS//DTD XML Catalogs V1.1//EN" "http://www.oasis-open.org/committees/entity/release/1.1/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<uri name="http://www.w3.org/1999/xhtml" uri="file:///home/me/code/base5html.xsd"/>
</catalog>
Ok, then I run it:
$ export XML_CATALOG_FILES=~/code/mycatalog.xml
$ export XML_DEBUG_CATALOG=1
$ xmllint --load-trace --noout --schema myschema.xsd test_doc.xml
Result (approx):
Loaded URL="myschema.xsd" ID="(null)"
Loaded URL="conf/b.xsd" ID="(null)"
Loaded URL="c.xsd" ID="(null)"
c.xsd:17: element element: Schemas parser error : Element '{http://www.w3.org/2001/XMLSchema}element', attribute 'ref': The QName value '{http://www.w3.org/1999/xhtml}p' does not resolve to a(n) element declaration.
c.xsd:18: element element: Schemas parser error : Element '{http://www.w3.org/2001/XMLSchema}element', attribute 'ref': The QName value '{http://www.w3.org/1999/xhtml}cite' does not resolve to a(n) element declaration.
c.xsd:26: element attributeGroup: Schemas parser error : Element '{http://www.w3.org/2001/XMLSchema}attributeGroup', attribute 'ref': The QName value '{http://www.w3.org/1999/xhtml}normAttrGrp' does not resolve to a(n) attribute group definition.
...
(more taken out)
...
WXS schema public/ctrl/lov.xsd failed to compile
Loaded URL="myschema.xml" ID="(null)"
Q: Isn't XSD+XMLCat a supported feature in libxml2 ?
( No hints to be found anywhere on the homepage : http://xmlsoft.org/catalog.html )

Get Nokogiri to not add "default" namespace when adding nodes

Background:
I want to take some xml from one file, put it in a template file and then save the modified template as a new file. It works, but when I save the file out, all the nodes that I added have a default namespace prepeneded, i.e.
<default:ComponentRef Id="C__AD1817F9C64A42F0A14DDDDC82DFC8D9"/>
<default:ComponentRef Id="C__157DD41D70854617A3D6D1E4A39B589F"/>
<default:ComponentRef Id="C__2E6D8662F38FE62CAFA9F8842A28F510"/>
<default:ComponentRef Id="C__54E5E2181323D4A5F37293DAA87B4230"/>
Which I want to be just:
<ComponentRef Id="C__AD1817F9C64A42F0A14DDDDC82DFC8D9"/>
<ComponentRef Id="C__157DD41D70854617A3D6D1E4A39B589F"/>
<ComponentRef Id="C__2E6D8662F38FE62CAFA9F8842A28F510"/>
<ComponentRef Id="C__54E5E2181323D4A5F37293DAA87B4230"/>
The following is my ruby code:
file = "wixmain/generated/DarkOutput.wxs"
template = "wixmain/generated/MsiComponentTemplate.wxs"
output = "wixmain/generated/MSIComponents.wxs"
dark_output = Nokogiri::XML(File.open(file))
template_file = Nokogiri::XML(File.open(template))
#get stuff from dark output
components = dark_output.at_css("Directory[Id='TARGETDIR']")
component_ref = dark_output.at_css("Feature[Id='DefaultFeature']")
#where to insert in template doc
template_component_insert_point = template_file.at_css("DirectoryRef[Id='InstallDir']")
template_ref_insert_point = template_file.at_css("ComponentGroup[Id='MSIComponentGroup']")
template_component_insert_point.children= components.children()
template_ref_insert_point.children= component_ref.children()
#write out filled template to output file
File.open(output, 'w') { |f| template_file.write_xml_to f }
Update
Example of my template file:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Fragment>
<ComponentGroup Id='MSIComponentGroup'>
</ComponentGroup>
</Fragment>
<Fragment Id='MSIComponents'>
<DirectoryRef Id='InstallDir'>
</DirectoryRef>
</Fragment>
</Wix>
Workaround was to remove the xmlns attribute in the input file.
Or to use the remove_namespaces! method when opening the input file
input_file = Nokogiri::XML(File.open(input))
input_file.remove_namespaces!
I think you are missing a sample of the template file. Also, is the sample from the input complete?
Nokogiri is either finding the default: namespace during its parsing of one of the two files, and you are inheriting it, or maybe it is not happy with the sample during parsing and is unable to parse cleanly, and as a result somehow adding the default: namespace. You can check the emptiness of the errors array after parsing the dark_output and template_file to see if Nokogiri is happy.
dark_output = Nokogiri::XML(File.open(file))
template_file = Nokogiri::XML(File.open(template))
if (dark_output.errors.any? || template_file.errors.any?)
[... do something here ...]
end
For the fastest answer, you might want to take this question directly to the developers via the Nokogiri-Talk mail-list.

Resources