There are lots of great Ruby libraries out there to generate XML documents, but I can't find any which support the generation of XML attributes with periods in their names.
The end goal here is to build a Ruby lib which auto generates Jenkins templates.
Here is an example Jenkins job field parameter, which as you can see, uses attributes with periods in the name:
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>MESSAGE</name>
<description/>
<defaultValue>Hello world!</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
Does anyone know how I could do this? Any way to bend the libraries which already exist to support this?
The solution is to use dynamic dispatching:
builder = Nokogiri::XML::Builder.new do |xml|
xml.properties {
xml.send('foo.bar', 'zaa')
}
end
<?xml version="1.0"?>
<properties>
<foo.bar>zaa</foo.bar>
</properties>
Related
I am using Maven Versions plugin's update-properties goal to update properties in pom.xml of multiples projects. (https://www.mojohaus.org/versions-maven-plugin/update-properties-mojo.html). I want the latest version of the dependency for properties.
Now, there are some binaries with wrong versions. I want my code to ignore these versions. For this, I have created my "rules.xml" file. I want to provide it as -DrulesUri argument to update-properties goal.
I already tried specifying this rules.xml file in pom.xml file of project as shown on (Maven versions plugin: reference a rule.xml from a maven dependency?). This worked as the plugin could successfully ignore specified versions in rules.xml. So, there is no problem with rules.xml file. But, this is not useful in my case, since there are many projects involved and I cannot update pom.xml of each project.
The documentation of rulesUri property says "URI of a ruleSet file containing the rules that control how to compare version numbers. The URI could be either a Wagon URI or a classpath URI (e.g. classpath:///package/sub/package/rules.xml)." This much documentation is not helping me. I would want an example on how to specify the rules.xml file in -DrulesUri argument. I tried specifying the rules.xml file as local relative path / absolute path. But, update-properties goal does not seem to recognize the rules and just proceeds similar to execution without -DrulesUri argument. I tried reading https://maven.apache.org/wagon/ to understand Wagon URIs. But, I did not find a simple way to upload my rules.xml somewhere and then use this Wagon URI to specify in -DrulesUri.
This is my rules.xml file :-
<?xml version="1.0" encoding="UTF-8"?>
<ruleset xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" comparisonMethod="maven" xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
<ignoreVersions>
<ignoreVersion type="regex">25243.*.*</ignoreVersion>
</ignoreVersions>
<rules>
</rules>
</ruleset>
Use -Dmaven.version.rules
Example:
mvn versions:display-dependency-updates -Dmaven.version.rules=file:///$HOME/.m2/rules.xml
From AbstractVersionsReport.java source code:
/**
* URI of a ruleSet file containing the rules that control how to compare
* version numbers. The URI could be either a Wagon URI or a classpath URI
* (e.g. <code>classpath:///package/sub/package/rules.xml</code>).
*
* #since 1.0-alpha-3
*/
#Parameter( property = "maven.version.rules" )
private String rulesUri;
I want to generate maven archetypes by using custom properties through archetype-metadata.xml's requiredProperty -
<requiredProperties>
<requiredProperty key="proxy-name">
<defaultValue>${proxy.name}</defaultValue>
</requiredProperty>
<requiredProperty key="proxy-desc">
<defaultValue>${proxy.description}</defaultValue>
</requiredProperty>
</requiredProperties>
However, my requirement is to initialize these requiredProperty values using key:value pairs provided either in a properties file or a yaml file, so that I can get these values injected in pom.xml of custom project structure under archetype-resources.
<properties>
<proxy-name>${proxy.name}</proxy-name>
<proxy-desc>>${proxy.description}</proxy-desc>
</properties>
I do not want to provide the values to these properties via command line or by providing default values. I want the initialization of these property values dynamic based on reading an external properties file when I run the mvn archetype:generate command.
Is this even possible? My apologies in advance if the question seems too vague or really elementary. This is my first experience dealing with custom maven archetypes.
P.S - I have tried using the yaml-properties-maven-plugin, however the values still don't get populated in archetype-resources pom.xml, which normally takes values when initializing property values via command line.
So, to answer my own question and to help anyone who is into the same problem:
What I did, is to also include an archetype.xml in META-INF/maven which takes in the resource properties file name to use to substitute custom values in the archetype-metadata.xml. Here's how the archetype.xml looks:
<?xml version="1.0" encoding="UTF-8"?>
<archetype>
<id>quickstart-archetype</id>
<sources/>
<resources>
<resource>archetype.properties</resource>
</resources>
</archetype>
This way the yaml-maven-properties plugin reads the yaml file and writes an archetype.properties file in the src/main/resources folder which also contains the archetype-resources folder structure for archetype generation.
Let me know in case anyone needs more clarification on how I achieved this.
I am trying to parse a POM file using Nokogiri, and want to get the first level child nodes.
My POM file looks something like this:
<project xmlns="some.maven.link">
<parent>
<groupId>parent.jar</groupId>
<artifactId>parent-jar</artifactId>
</parent>
<groupId>child.jar</groupId>
<artifactId>child-jar</artifactId>
</project>
I am trying to fetch the artifactId "child-jar" but the XPath that I am using is possibly incorrect and it's fetching me "parent.jar" as the first occurence.
This is my Ruby code:
#pom = Nokogiri::XML(File.open(file_path))
p #pom.xpath("/project/artifactId", project"=>"http://maven.apache.org/POM/4.0.0")[0].text
I can access the second element but that just would be a hack.
Your XML sample does not appear to be correct. Simplifying it:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<project>
<parent>
<groupId>parent.jar</groupId>
<artifactId>parent-jar</artifactId>
</parent>
<groupId>child.jar</groupId>
<artifactId>child-jar</artifactId>
</project>
EOT
doc.at('project > artifactId').text # => "child-jar"
Using XPath I'd use:
doc.at('/project/artifactId').text # => "child-jar"
I'd suggest learning the difference between search, xpath, css and their at* cousins which are all documented in the "Searching a XML/HTML Document" and Node documentation.
In the above example I removed the XML namespace information to simplify things. XML namespaces are useful, but also are irritating and in your example XML you'd broken it by not supplying a valid URL. Fixing the example with:
<project xmlns="http://www.w3.org/1999/xhtml">
I can use:
namespaces = doc.collect_namespaces # => {"xmlns"=>"http://www.w3.org/1999/xhtml"}
doc.at('project > artifactId', namespaces).text # => "child-jar"
or:
doc.at('xmlns|project > xmlns|artifactId').text # => "child-jar"
I prefer and recommend the first because it's more readable and less noisy.
Nokogiri's implementation of CSS in selectors helps simplify most selectors. Passing in the collected namespaces in the document simplifies searches, whether you're using CSS or XPath.
These also work:
doc.at('/xmlns:project/xmlns:artifactId').text # => "child-jar"
doc.at('/foo:project/foo:artifactId', {'foo' => "http://www.w3.org/1999/xhtml"}).text # => "child-jar"
Note that the second uses a renamed namespace, which is useful if you're dealing with redundant xmlns declarations in the document and need to differentiate between them.
Nokogiri's "Namespaces" tutorial is helpful.
I am trying to template various XML files. What I want to do is be able to build out a Parent XML by including several Child XML files. This should happen during the expand()->copy() using the SimpleTemplateEngine
as an example:
Gradle:
processResources {
exclude '**/somedir/*'
propList.DESCRIPTION = 'a description goes here'
expand(propList)
}
Parent.XML:
<xml>
<line1>something</line1>
<%include file="Child.XML" %>
</xml>
The documentation states that the SimpleTemplateEngine uses JSP <% syntax and <%= expressions, but does not necessarily provide a list of supported functions.
include fails with it not being a valid method on the resulting SimpleTemplateScript, maybe I meant eval?
The closest I've come to getting something to work is:
<xml>
<line1>something</line1>
<% evaluate(new File("Child.xml")) %>
</xml>
That results in 404 of the Child.xml as it's looking at the process working directory, rather than that of the Parent file. If I reference it as "build/resources/main/templates..../Child.xml", then I get 'unexpected token: < # line....' errors from parsing the Child.
Can this be done? Do I need to change template engines, if that's even possible? Ideally it should process any tokens in Child as well.
This is all very simple in JSP. I somehow got the impression I can treat these files like they're GSP, but I'm not sure how to properly use the GSP tags, if that's even true.
Any help, as always, is greatly appreciated.
Thank you.
This documentation doesn't mention JSP. The syntax for the SimpleTemplateEngine is ${}.
Using Gradle 3.4-rc2, if I have this build.gradle file:
task go(type: ProcessResources) {
from('in') {
include 'root.xml'
}
into 'out'
def props = [:]
props."DESCRIPTION" = "description"
expand(props)
}
where in/root.xml is:
<doc>
<name>root</name>
<desc>${DESCRIPTION}</desc>
${new File("in/childA.xml").getText()}
</doc>
and in/childA.xml is:
<child>
<name>A</name>
</child>
then the output is:
<doc>
<name>root</name>
<desc>description</desc>
<child>
<name>A</name>
</child>
</doc>
I have a problem, what I cannot solve.
I want to build my eclipse cdo server with Tycho/Maven and also I want to have the prossibility to start my cdo-server.product out of eclipse.
The cdo server it set up like this: http://wiki.eclipse.org/Setting_up_a_CDO_Server
No there is my problem:
If I choose:
-Dnet4j.config="${resource_loc:/cdo.server/config}"
I can start it out of eclipse, but if I want to start the built CDO-Server.app it cannot find this folder.
If I choose:
-Dnet4j.config="../../../../../../../../../../cdo.server/config"
I can start the built CDO-Server.app, but I can't start it ou of eclipse.
This is all logical, but now I decided to make ${resource_loc:/cdo.server/config} as a property in my pom.xml file.
But if I write it like this:
<properties>
<resource_loc:/cdo.server/config>../../../../../../../../../../cdo.server/config</resource_loc:/cdo.server/config>
</properties>
I get the exception, that this is not a parseable POM because of the slash in the tag.
If I want to make it like this:
<properties>
<resource_loc:>
<cdo.server>
<config>../../../../../../../../../../cdo.server/config</config>
</cdo.server>
</resource_loc:>
</properties>
It also is not a parseable POM. Is there any possibility to use ${resource_loc:/cdo.server/config} as a property?
The problem in your property definition are the slashes in the name of the property.
The following will fail parsing the pom.xml:
<resource_loc:/cdo.server/config>yx</resource_loc:/cdo.server/config>
or
WhatEverValue
It will also not working if you try to use / as a replacement for the slash in the entity name.
you may want to try http://mojo.codehaus.org/properties-maven-plugin/read-project-properties-mojo.html to read the properties from a separate file instead in order to get around the XML well-formedness limitation in pom.xml.