Question

I have a XML file where I want to replace the password for a specific user. With the use of ANT and xsl file I want replace the old password ie password1

xml file

<connector-factory connector-name="JmsAdapter" location="eis/wljms/Src">
    <config-property name="username" value="username1"></config-property>
    <config-property name="password" value="password1"></config-property>
    <log>
      <file path="/var/log/logfile.log"></file>
    </log>
</connector-factory>
<connector-factory connector-name="JmsAdapter" location="eis/wljms/Src">
    <config-property name="username" value="username2"></config-property>
    <config-property name="password" value="password2"></config-property>
</connector-factory>
<connector-factory connector-name="JmsAdapter" location="eis/wljms/Src">
    <config-property name="username" value="username3"></config-property>
    <config-property name="password" value=""></config-property>
    <log>
      <file path="/var/log/logfile.log"></file>
    </log>
</connector-factory>

xsl file

<?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
        <xsl:template match="@*|node()">
            <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>
   <xsl:template match="config-property/@value[. =  'username1']">
            <config-property name="username" value="username1"/>
            <config-property name="password" value="PASSWD_DBLINK"/>
        </xsl:template>
 </xsl:stylesheet>

build xml

<target name="JmsAdapter">
   <property name="tmp.file" value="JmsServer-oc4j-ra.tmp"/>
   <xslt in="oc4j-ra.xml" out="${tmp.file}" style="JmsServer-oc4j-ra.xsl">
   <outputproperty name="method" value="xml"/>
   </xslt>
   <replaceregexp file="${tmp.file}" match="PASSWD_DBLINK" replace="${PASSWD_DBLINK}" byline="true"/>
   <xmltask outputter="simple" source="${tmp.file}" dest="${tmp.file}">
   <remove path="/oc4j-connector-factories/connector-factory/config-property/@value[.='username1']"/>
   <remove path="/oc4j-connector-factories/connector-factory/config-property/@name[.='password']"/>
   </xmltask>
   </target>

The result obviously is, that the password is changed to the correct value, however because of this line

<remove path="/oc4j-connector-factories/connector-factory/config-property/@name[.='password']"/>

all the other passwords where deleted and this is not what I want. Without this statement the password entry is appended to the file, and I don't want this either.

My question is how to replace the password only in the correct path, where for example value=username1, and not everywhere else.

Was it helpful?

Solution

You can do the whole thing with xmltask using the replace option with a slightly more specific XPath expression:

<xmltask outputter="simple" source="${tmp.file}" dest="${tmp.file}">
  <replace withText="${PASSWD_DBLINK}"
     path="/oc4j-connector-factories/connector-factory[
              config-property[@name='username'][@value = 'username1']
           ]/config-property[@name='password']/@value"/>
</xmltask>

Here I'm using a predicate at the connector-factory level to select only the connector-factory with username "username1", and then modifying its password property.

Alternatively with XSLT

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

  <!-- to pass in the new password value from Ant -->
  <xsl:param name="newPassword" />

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <!-- replace the password value for username1 only -->
  <xsl:template match="connector-factory[
          config-property[@name = 'username'][@value =  'username1']
        ]/config-property[@name = 'password']/@value">
    <xsl:attribute name="value">
      <xsl:value-of select="$newPassword" />
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

and call it from Ant with

<xslt in="oc4j-ra.xml" out="${tmp.file}" style="JmsServer-oc4j-ra.xsl">
  <param name="newPassword" expression="${PASSWD_DBLINK}"/>
</xslt>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top