I'm new with groovy (a few weeks of experience). Currently I'm trying to process some visual studio .vcproj files using groovy: replacing some paths, that will be found by a regexp patterns. This works fine for me.
To write the changes to the file, I'm using the
XmlUtil.serialize(slurper, writer)
method, where
def writer = new FileWriter(outputFile)
and
def slurper = new XmlSlurper(keepIgnorableWhitespace:true).parse(it)
This also works fine, except one thing.
In the original vcproj file each attribute is in a separate line, like:
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\..\..\..\Test_Debug.vsprops"
CharacterSet="2"
>
but after calling the serialize() method of the XMLUtil class, the whole output is stored in one line:
<Configurations>
<Configuration Name="Debug|Win32" InheritedPropertySheets="..\..\..\..\Test_Debug.vsprops" OutputDirectory="$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="1" CharacterSet="2">
for the XMS parser this should be not a problem, but in the postprocessing some perl scripts use this vcproj file and they complain about missing CR/LF within the attribute line.
So is there any easy possibility to configure the XMLslurper or the serialize-class to keep the CR/LF in between of each attributes?
I doubt there is any easy way to format groovy's xml output to that level. Since the output is a valid XML, can't you use somekind of perl XML parser?
Other than that, you can try to match the attributes with a regex and add a line break to them. A very ugly hack:
import groovy.xml.XmlUtil
def original = '''<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\\..\\..\\..\\Test_Debug.vsprops"
CharacterSet="2"
>
</Configuration>
</Configurations>
'''
parsed = new XmlParser().parseText original
println XmlUtil.serialize(parsed).replaceAll(/[a-zA-Z]*="[^\"]*"/) {
"\n" + it
}
will print:
<?xml
version="1.0"
encoding="UTF-8"?><Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets="..\..\..\..\Test_Debug.vsprops"
CharacterSet="2"/>
</Configurations>
Related
I am attempting to link resource files that were organized by locale folders into their own .resources.dll assembly. There are more than 750 locales that are dynamically generated, so it is not practical to hard code them like the docs show.
<ItemGroup>
<ResourceFiles Include="<path_to>/af/af.res;<path_to>/af/feature1.af.res;<path_to>/af/feature2.af.res">
<Culture>af<Culture>
</ResourceFiles>
<ResourceFiles Include="<path_to>/af-NA/af_NA.res;<path_to>/af-NA/feature1.af_NA.res;<path_to>/af-NA/feature2.af_NA.res">
<Culture>af-NA<Culture>
</ResourceFiles>
<ResourceFiles Include="<path_to>/af-ZA/af_ZA.res;<path_to>/af-ZA/feature1.af_ZA.res;<path_to>/af-ZA/feature2.af_ZA.res">
<Culture>af-ZA<Culture>
</ResourceFiles>
</ItemGroup>
The above structure can be used to execute the AL task multiple times for each group of files. As you can see, my files are arranged in folders that are named the same as the culture in .NET.
My question is, how do I build this structure dynamically based on the 750+ locale folders, many which contain multiple files?
What I Tried
I was able to get the grouping to function. However, for some odd reason the list of files is being evaluated as a String rather than ITaskItem[] like it should be. This is the structure that does the correct grouping. It is based on this Gist (although I am not sure whether I am misunderstanding how to use the last bit because the example is incomplete).
<PropertyGroup>
<SatelliteAssemblyTargetFramework>netstandard2.0</SatelliteAssemblyTargetFramework>
<TemplateAssemblyFilePath>$(MSBuildProjectDirectory)/bin/$(Configuration)/$(TargetFramework)/$(AssemblyName).dll</TemplateAssemblyFilePath>
<ICU4JResourcesDirectory>$(SolutionDir)_artifacts/icu4j-transformed</ICU4JResourcesDirectory>
<ICU4NSatelliteAssemblyOutputDir>$(SolutionDir)_artifacts/SatelliteAssemblies</ICU4NSatelliteAssemblyOutputDir>
<PropertyGroup>
<Target
Name="GenerateOurSatelliteAssemblies"
DependsOnTargets="ExecICU4JResourceConverter"
AfterTargets="AfterBuild"
Condition=" '$(TargetFramework)' == '$(SatelliteAssemblyTargetFramework)' ">
<ItemGroup>
<EmbeddedResources Include="$(ICU4JResourcesDirectory)/*.*" />
<EmbeddedResourcesPaths Include="$([System.IO.Directory]::GetDirectories('$(ICU4JResourcesDirectory)'))" />
<!-- This groups each locale together along with its nested files and root path -->
<FolderInLocale Include="#(EmbeddedResourcesPaths)">
<Culture>$([System.IO.Path]::GetFileName('%(Identity)'))</Culture>
<Files>$([System.IO.Directory]::GetFiles('%(EmbeddedResourcesPaths.Identity)'))</Files>
</FolderInLocale>
</ItemGroup>
<!-- EmbedResources accepts ITaskItem[], but the result
of this transform is a ; delimited string -->
<AL EmbedResources="#(FolderInLocale->'%(Files)')"
Culture="%(FolderInLocale.Culture)"
TargetType="library"
TemplateFile="$(TemplateAssemblyFilePath)"
KeyFile="$(AssemblyOriginatorKeyFile)"
OutputAssembly="$(ICU4NSatelliteAssemblyOutputDir)/%(FolderInLocale.Culture)/$(AssemblyName).resources.dll" />
</Target>
I have attempted numerous ways to replace the semicolon characters with %3B and to split on semicolon (i.e. #(FolderInLocale->'%(Files.Split(';'))'), but in all cases, the transform fails to evaluate correctly.
I have also consulted the docs for MSBuild well-known item metadata to see if there is another way of grouping by folder. Unfortunately, there is no %(FolderName) metadata, which would solve my issue completely. While I was able to get it to group by folder using the below XML, it immediately flattened when trying to get the name of the top level folder, which is where the name of the culture is.
I am using GetFileName() to get the name of the top level folder after stripping the file name from it. But please do tell if there is a better way.
<ItemGroup>
<EmbeddedResourcesLocalizedFiles Include="$(ICU4JResourcesDirectory)/*/*.*"/>
<EmbeddedResourcesLocalized Include="#(EmbeddedResourcesLocalizedFiles)">
<Culture>%(RootDir)%(Directory)</Culture>
</EmbeddedResourcesLocalized>
<!-- Calling GetFileName() like this rolls the files into a single group,
but prior to this call it is grouped correctly. -->
<EmbeddedResourcesLocalized2 Include="#(EmbeddedResourcesLocalized)">
<Culture>$([System.IO.Path]::GetFileName('%(EmbeddedResourcesLocalized.Culture)'))</Culture>
</EmbeddedResourcesLocalized2>
</ItemGroup>
Below is my xml input:
<projects>
<project>
<name >project1</name>
<language>java</language>
</project>
<project>
<name>project2</name>
<language>mainframe</language>
</project>
</projects>
I want to convert this .xml to .csv file using data-mapper, but unfortunately it doesn't work.
Can anyone send me the sample flow xml for that? It is very important for my project now.
This is a very simple requirement.
You should select your sample XML file in the input section of the datamapper and define a user defined output of type CSV. Once you create a mapping, map the fields from XML (input) to CSV (output). The code would like as below.
//MEL
//START -> DO NOT REMOVE
output.__id = str2long(input.__id);
//END -> DO NOT REMOVE
output.name = input.name;
output.language = input.language;
You can now click on Preview button and run the preview with your sample XML file. Wasn't that easy? Try this and let me if any issues.
I have created an XML file using streamWriter.. Now, i want to remove the line breaks in my XML file.. Is there a way to accomplish this task..?
here's my sample outout
<?xml version="1.0" encoding="utf-8"?>
<!--Arbortext, Inc., 1988-2004, v.4002-->
<!DOCTYPE primary.hierarchy SYSTEM "http://phoenix.roc.westgroup.com/dtd/pax.dtd">
Output should look like this
<?xml version="1.0" encoding="utf-8"?><!--Arbortext, Inc., 1988-2004, v.4002--><!DOCTYPE primary.hierarchy SYSTEM "http://phoenix.roc.westgroup.com/dtd/pax.dtd">
Instead of using StreamWriter you can consider using XmlWriter instead. It has various settings to deal with formatting of XML output.
See XmlWriterSettings for details
BTW. I assume that have you used WriteLine with your StreamWriter approach use Write instead. That should get rid of your line breaks.
I'd like to take text from a standard text file and insert it into an XML that is copied with replace tokens by Apache Ant. Is this possible?
Example (this is what I use so far):
<macrodef name="generateUpdateFile">
<sequential>
<echo message="Generating update file ..." level="info"/>
<copy file="update.xml" tofile="${path.pub}/update.xml" overwrite="true">
<filterchain>
<replacetokens>
<token key="app_version" value="${app.version}"/>
<token key="app_updatenotes" value="${app.updatenotes}"/>
</replacetokens>
</filterchain>
</copy>
</sequential>
</macrodef>
The ${app.updatenotes} are currently a string that is defined in a build.properties file. But instead I'd like to write update notes in a simple text file and take them from there.
The apache ant loadfile task will allow to read your text file, and put its content into the app.updatenotes property.
You can simply use:
<loadresource property="app.updatenotes">
<file file="notes.txt"/>
</loadresource>
Then, use your filterchain, just as before.
loadresource has some options, for instance to control the encoding of your file, or to control how to react if the file is not present, or not readable.
I need to construct an MSBUILD script executes .SQL Scripts which have changed since last build.
I initially thought that I could copy all scripts from one folder to another using the <Copy> task and using the CopiedFiles <Output> for the copy task. However the copy task returns All files that it Attempted to copy, not actual copied files.
I am able to get MSBUILD to execute SQL Scripts via MSBUILD.ExtensionPack but Im scratching my head on this one
You can do this with a concept known as incremental building. The idea is that you would create a target and then specify the inputs and outputs, which would be files. MSBuild will compare the timestamps of the input files to the output files. If all outputs were created after all outputs then the target is skipped. If all inputs are newer then all the target will be executed for all files. If only a portion are out of date, then only those will be passed to the target. For more info on this see the section Using Incremental Builds in my article Best Practices For Creating Reliable Builds, Part 2.
Also for more resources on MSBuild I have compiled a list at http://sedotech.com/Resources#MSBuild
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="RunScripts">
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.tasks"/>
<PropertyGroup>
<ConnStr>Server=Example;Database=Example;Trusted_Connection=True</ConnStr>
<BuildFolder>Build\</BuildFolder>
</PropertyGroup>
<ItemGroup>
<Scripts Include="*.sql"/>
</ItemGroup>
<Target Name="RunScripts"
Inputs="#(Scripts)"
Outputs="#(Scripts->'$(BuildFolder)%(Filename)%(Extension)')">
<SqlExecute TaskAction="ExecuteScalar"
Files="#(Scripts)"
ConnectionString="$(ConnStr)"/>
<Copy SourceFiles="#(Scripts)"
DestinationFiles="#(Scripts->'$(BuildFolder)%(Filename)%(Extension)')"/>
</Target>
</Project>
Could it be that you copying into an empty destination?
SkipUnchangedFiles
If true, skips the copying of files that are unchanged
between the source and destination. The Copy task considers
files to be unchanged if they have the same size and the
same last modified time.
In your case i suspect that all files are considered changed since they don't exist at the destination.