How to use profiles or targets to get the values f

2019-08-18 03:06发布

问题:

Using Maven or Ant wanted to get the values from an xml file and replace it by its variables using targets/profiles.

properties.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<variables>
    <variable id="Title">
      <book.01>abc</book.01>
      <book.02>def</book.01>
      <ebook.03>ghi</book.01>
      <ebook.04>klmn</book.01>
    </variable>
    <variable id="Author">
      <book.01>john</book.01>
      <book.02>jack</book.01>
      <ebook.03>simi</book.01>
      <ebook.04>laura</book.01>
    </variable>
</variables>

Using Maven or Ant if I select "book.01" as target or profile, I want to replace the values in Template.xml with values of "book.01" from properties.xml

Current Template.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<projects>
    <mbean code="org.jboss.naming.JNDIBindingServiceMgr"
        name="abc.jndi:name=JNDIProp">
        <attribute name="myprop" serialDataType="jbxb">
            <jndi:bindings
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">               
                <jndi:binding
                    name="Title">
                    <jndi:value type="java.lang.String">
                        @book.01@
                    </jndi:value>
                </jndi:binding>
                <jndi:binding name="Author">
                    <jndi:value type="java.lang.String">
                        @book.01@
                    </jndi:value>
                </jndi:binding>
            </jndi:bindings> 
        </attribute>
    </mbean>
<projects>

Expected output is:book.01.xml

<?xml version="1.0" encoding="UTF-8"?>
<projects>
    <mbean code="org.jboss.naming.JNDIBindingServiceMgr"
        name="abc.jndi:name=JNDIProp">
        <attribute name="myprop" serialDataType="jbxb">
            <jndi:bindings
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">               
                <jndi:binding
                    name="Title">
                    <jndi:value type="java.lang.String">
                        abc
                    </jndi:value>
                </jndi:binding>
                <jndi:binding name="Author">
                    <jndi:value type="java.lang.String">
                        john
                    </jndi:value>
                </jndi:binding>
            </jndi:bindings> 
        </attribute>
    </mbean>
<projects>

But wanted to know how should i use same template when i want to run the values for "book.02" or "ebook.03" profiles/target.

Note: The maven profile name/ant target name will be matching the variables of template.xml @varaible@ name. Example: mvn -P book.01 or ant ebook.01

UPDATES:

With the help of @Ken xsl stylesheet file, I have used the xml-maven plugin to transform the template.xml.Using maven-replacer-plugin I was able to change the @book.01@ varaible in template.xml and replace it with the profile name.

Example:

   <profile>
        <id>book.02</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <build>
    <plugins>
        <plugin>
            <groupId>com.google.code.maven-replacer-plugin</groupId>
            <artifactId>replacer</artifactId>
            <executions>
                <execution>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>replace</goal>
                    </goals>                    
                </execution>
            </executions>
            <configuration>
                <ignoreMissingFile>true</ignoreMissingFile>
                <file>template.xml</file>
                <outputFile>
                    target/template.xml
                </outputFile>
                <regex>false</regex>
                <token>@book.01@</token>
                <value>@book.02@</value>
            </configuration>
        </plugin>
    </plugins>

回答1:

Are you asking for help, or are you asking for people to solve your entire problem for you? It is obvious that you haven't worked with the above data files because neither of them are well-formed. You are asking volunteers to fix your XML before giving you a complete answer. I suggest in the future that you try to solve the problem first and then ask questions. That way you can be directed regarding where you are having a problem in your understanding, and the files that you post will at least be well-formed.

A solution is below, as I suspect other readers may be interested in the approach using <xsl:analyze-string>.

t:\ftemp>type properties.xml

<?xml version="1.0" encoding="UTF-8"?>
<variables>
    <variable id="Title">
      <book.01>abc</book.01>
      <book.02>def</book.02>
      <ebook.03>ghi</ebook.03>
      <ebook.04>klmn</ebook.04>
    </variable>
    <variable id="Author">
      <book.01>john</book.01>
      <book.02>jack</book.02>
      <ebook.03>simi</ebook.03>
      <ebook.04>laura</ebook.04>
    </variable>
</variables>

t:\ftemp>type Template.xml

<?xml version="1.0" encoding="UTF-8"?>
<projects>
    <mbean code="org.jboss.naming.JNDIBindingServiceMgr"
        name="abc.jndi:name=JNDIProp">
        <attribute name="myprop" serialDataType="jbxb">
            <jndi:bindings
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">               
                <jndi:binding
                    name="Title">
                    <jndi:value type="java.lang.String">
                        @book.01@
                    </jndi:value>
                </jndi:binding>
                <jndi:binding name="Author">
                    <jndi:value type="java.lang.String">
                        @book.01@
                    </jndi:value>
                </jndi:binding>
            </jndi:bindings> 
        </attribute>
    </mbean>
</projects>

t:\ftemp>call xslt2 Template.xml properties.xsl

<?xml version="1.0" encoding="UTF-8"?><projects>
    <mbean code="org.jboss.naming.JNDIBindingServiceMgr" name="abc.jndi:name=JNDIProp">
        <attribute name="myprop" serialDataType="jbxb">
            <jndi:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xmlns:jndi="urn:jboss:jndi-binding-service:1.0" xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">               
                <jndi:binding name="Title">
                    <jndi:value type="java.lang.String">
                        abc
                    </jndi:value>
                </jndi:binding>
                <jndi:binding name="Author">
                    <jndi:value type="java.lang.String">
                        john
                    </jndi:value>
                </jndi:binding>
            </jndi:bindings> 
        </attribute>
    </mbean>
</projects>

t:\ftemp>type properties.xsl

<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

<xsl:key name="props" match="variable/*"
         use="concat(../@id,'&#xd;',name(.))"/>

<xsl:template match="j:value" xmlns:j="urn:jboss:jndi-binding-service:1.0">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:variable name="id" select="../@name"/>
    <xsl:analyze-string select="." regex="@(.*?)@">
      <xsl:matching-substring>
        <xsl:value-of
          select="key('props',concat($id,'&#xd;',regex-group(1)),
                      doc('properties.xml'))"/>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
        <xsl:value-of select="."/>
      </xsl:non-matching-substring>
    </xsl:analyze-string>
  </xsl:copy>
</xsl:template>

<xsl:template match="@*|node()"><!--identity for all other nodes-->
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

t:\ftemp>rem Done!



回答2:

You can use an XSLT transformation to generate XML files. ANT has a built in xslt task.

Example

├── build.xml
├── src
│   └── resources
│       ├── properties.xml
│       └── template1.xsl
└── target
    └── result.xml

build.xml

<project name="demo" default="transform">

   <property name="resources.dir" location="src/resources"/>
   <property name="build.dir"     location="target"/>

   <target name="transform">
      <xslt style="${resources.dir}/template1.xsl" in="${resources.dir}/properties.xml" out="${build.dir}/result.xml"/>
   </target>

   <target name="clean">
      <delete dir="${build.dir}"/>
   </target>

</project>

properties.xml

Your original data was not well-formed. This is my assumption of the correct file content:

<?xml version="1.0" encoding="UTF-8"?>
<variables>
    <variable id="Title">
      <book.01>abc</book.01>
      <book.02>def</book.02>
      <ebook.03>ghi</ebook.03>
      <ebook.04>klmn</ebook.04>
    </variable>
    <variable id="Author">
      <book.01>john</book.01>
      <book.02>jack</book.02>
      <ebook.03>simi</ebook.03>
      <ebook.04>laura</ebook.04>
    </variable>
</variables>

template1.xsl

This is the stylesheet used as a template for the output file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xmlns:xalan="http://xml.apache.org/xslt"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">

   <xsl:output method="xml" indent="yes" xalan:indent-amount="4"/>

   <xsl:template match="/">
      <projects>
         <mbean code="org.jboss.naming.JNDIBindingServiceMgr" name="abc.jndi:name=JNDIProp">
            <attribute name="myprop" serialDataType="jbxb">
               <jndi:bindings xmlns:jndi="urn:jboss:jndi-binding-service:1.0" >               
                  <xsl:apply-templates select="//variable[@id='Title']/book.01"  mode="title"/>
                  <xsl:apply-templates select="//variable[@id='Author']/book.01" mode="author"/>
               </jndi:bindings> 
            </attribute>
         </mbean>
      </projects>
   </xsl:template>

   <xsl:template match="book.01" mode="title">
      <jndi:binding name="Title">
         <jndi:value type="java.lang.String"><xsl:value-of select="."/></jndi:value>
      </jndi:binding>
   </xsl:template>

   <xsl:template match="book.01" mode="author">
      <jndi:binding name="Author">
         <jndi:value type="java.lang.String"><xsl:value-of select="."/></jndi:value>
      </jndi:binding>
   </xsl:template>

</xsl:stylesheet>

Notes:

  • This example uses XSL template modes to match different "book.01" tags dependent on different XPATH search criteria.

result.xml

The generated output:

<?xml version="1.0" encoding="UTF-8"?>
<projects xmlns:xalan="http://xml.apache.org/xslt" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xmlns:jndi="urn:jboss:jndi-binding-service:1.0">
    <mbean code="org.jboss.naming.JNDIBindingServiceMgr" name="abc.jndi:name=JNDIProp">
        <attribute name="myprop" serialDataType="jbxb">
            <jndi:bindings>
                <jndi:binding name="Title">
                    <jndi:value type="java.lang.String">abc</jndi:value>
                </jndi:binding>
                <jndi:binding name="Author">
                    <jndi:value type="java.lang.String">john</jndi:value>
                </jndi:binding>
            </jndi:bindings>
        </attribute>
    </mbean>
</projects>