cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
jchristman
Level 8

XML Installscript

I am looking for a way to read a web.config that exists on the server that Is being installed on. Find a couple of specific tags and store the information then after the installation of the new files place these values into the web.config that was installed.
Labels (1)
0 Kudos
(21) Replies
Christopher_Pai
Level 16

XML System Search and XML Changes can do this. It requires a decent understanding of XPath statements though.
0 Kudos
jchristman
Level 8

The XML File Changes section is new to me. I can see how I can add information into an XML file, not for sure though how I can read information out of a XML file that is already on the target machine. I would like to be able to read in areas like appsettings and get the key and the value and display them in a dialog before the installation actually starts then based on what was read in the installer might do differant things through the dialog process. Once the installation actually starts it will probably overwrite some xml files with updated versions but needs to add back installation specific settings that were in the XML file that was already on the target machine.
0 Kudos
Christopher_Pai
Level 16

Take a look at Behavior & Logic | System Search.
0 Kudos
jchristman
Level 8

I do not have a system search. This is an Installscript project.
0 Kudos
Christopher_Pai
Level 16

Oh, sorry. You'll have to write script to call the Microsoft XML Dom objects to do a query.
0 Kudos
jchristman
Level 8

I have been searching the forums and online for installscript examples to read in information from an XML file but with no luck.

Could some one post a couple of sample scripts of an installscript function that reads an XML file like web.config and one that updates an XML file like web.config.

I mention web.config since it is one of the easiest to reference. I am looking to write an Installscript that can work with web.config files and with the METABASE.XML for IIS6+
0 Kudos
TheTraveler
Level 8

Here is a little piece of code that I used to modify our web.config file to change the SQLConnection String. This is a good example on how to modify XML files in Install Shield Script. Keep in mind, I got a lot of how to do this from this forum...

#define ERROR_SUCCESS 0
#define ERROR_XML_FILE_CREATION "Setup could not find the web.config file %s"
#define ERROR "Error"
#define ERROR_XML_FILE_STRUCTURE "The web.config file structure is corrupted.%s"
#define ERROR_XML_FILE_LOAD "The web.config file was not loaded.%s"

prototype ModifyWebConfig(BYVAL STRING, BYREF STRING);

///////////////////////////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////////////////////////
function ModifyWebConfig(strFileName, strError)
OBJECT oDoc, oNode, oNodeList;
NUMBER i, nSize;
STRING strNamedItem;
STRING strValue;
begin
///////////////////////////////////////////////////////////////////////////
// Check to see if the file exists... //
///////////////////////////////////////////////////////////////////////////
if Is(FILE_EXISTS, strFileName) = TRUE then
//MessageBox("XML file exists",0);
else
MessageBox("XML file is missing",0);
endif;

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
nSize = 300;
i = 0;
// "Data Source="+ m_strDBDataSource +";"+
strValue = "Data Source=" + m_strDBDataSource;
strValue = strValue +";User Id=" + m_strDBUserName;
strValue = strValue +";Password=" + m_strDBPassword;
strValue = strValue +";Initial Catalog="+ m_strDBName;
strValue = strValue +";Persist Security Info=True";
if m_strADOConnectionTimeout != "" then
strValue = strValue +";Connection Timeout="+ m_strADOConnectionTimeout;
else
strValue = strValue +";Connection Timeout="+ SQL_CONNECTION_TIMEOUT;
endif;

///////////////////////////////////////////////////////////////////////////
// get values from public properties
///////////////////////////////////////////////////////////////////////////
set oDoc = CreateObject("Msxml2.DOMDocument.4.0");
if (IsObject(oDoc) = FALSE) then
MessageBox(ERROR_XML_FILE_CREATION, 0);
return -1;
endif;
oDoc.async = FALSE;
oDoc.setProperty("SelectionLanguage", "XPath");

///////////////////////////////////////////////////////////////////////////
// if success, traverse file and substitute value //
///////////////////////////////////////////////////////////////////////////
if oDoc.load(strFileName) then
///////////////////////////////////////////////////////////////////////
// get list of matching nodes //
///////////////////////////////////////////////////////////////////////
set oNodeList = oDoc.getElementsByTagName("*");
if (oNodeList.length > 0) then
for i = 0 to (oNodeList.length - 1);
set oNode = oNodeList.nextNode;
try
strNamedItem = oNode.attributes.getNamedItem("key").value;
catch
strNamedItem = "";
endcatch;

try
if strNamedItem = "SQLConnection" then
oNode.attributes.getNamedItem("value").value = strValue;
endif;
catch
endcatch;
endfor;
else
MessageBox(ERROR_XML_FILE_STRUCTURE,SEVERE);
return -1;
endif;
else
MessageBox(ERROR_XML_FILE_LOAD,SEVERE);
return -1;
endif;

oDoc.save(strFileName);
set oDoc = NOTHING;
end;
0 Kudos
jchristman
Level 8

Thank you very much, I have been looking through the forums and online and most of what I had found was about MSI and builds. I will start changing up they way I run searches in these forums. Thank you for letting me know that most of the information I probably seek is in the forums. 🙂
0 Kudos
jcouvret
Level 2

I started with the script provided by The Traveler, however I was needing to edit a somewhat complicated XML file created by a different software package that included a default namespace and was failing the DTD Schema verification. I got around this by figuring out how to define the namespace(s) to search under in XPath and using an older version of DOM that didn't do the DTD verification. Here is the code with explanation if it can help anyone else avoid several days of learning about XPath and namespaces.

[CODE]prototype ModifyXmlAttribute( STRING , NUMBER , STRING , STRING , STRING , STRING );

/*////////////////////////////////////////////////////////////////////////////////////
function ModifyXmlAttribute

Description: This function changes the value of an attribute associated with
one or more elements defined by an Xpath statement. If there are
multiple elements matching the Xpath statement, this function will
offer to change the attributes of all matching elements, or abort.

Inputs: svFile = The full path to the XML file to modify.
nNamespace = 1 to use namespace in search, 0 to not use namespace.
svNamespace = Only used if nNamespace = 1. This the namespace to be used
in the Xpath search string. If not used, enter "" for value.
svXpath = The Xpath statement that defines the element(s) containing the
attribute to be modified.
svAttribute = The name of the attribute to be modified.
svValue = The value to be written to the specified attribute.

Return: 0 - The attributes of all matching elements were successfully changed.
Greater than 0 - Some or all attribute changes failed.

Example:
XML File:













Function Variables:
svFile = "Path\\to\\your\\file.xml"
nNamespace = 1
svNamespace = "xmlns:pro='http://deltabis.com/products' xmlns:itin='http://deltabis.com/itinerary'"
svXpath = "//pro:lists/pro:product[@type='tshirt']/itin:itinerary"
svAttribute = "sold"
svValue = "1000"

Result:
Before:
After:

Notes: If a default namespace is defined (xmlns=something) in the XML file, that
namespace will have to be defined or the Xpath search will not return any
elements. For more information, go to http://www.xml.com/lpt/a/979
*////////////////////////////////////////////////////////////////////////////////////

function ModifyXmlAttribute( svFile , nNamespace , svNamespace , svXpath , svAttribute , svValue )
OBJECT oDoc, oNode, oNodeList, oDocType;
STRING svMessage, svError, svLine, svLinePos;
NUMBER i, nFailed;
begin

nFailed = 0;

// Check to see if the file exists...
if Is( FILE_EXISTS , svFile ) = FALSE then
MessageBox("XML file does not exist.",0);
return 1;
endif;

//Set XML DOM Object
set oDoc = CreateObject( "Microsoft.XMLDOM" );
if ( IsObject( oDoc ) = FALSE ) then
MessageBox( "MSXML DOM-Document Connection Failed" , 0 );
return 1;
endif;
oDoc.async = FALSE;

//Set namespace and load file
oDoc.setProperty( "SelectionLanguage" , "XPath" );
oDoc.setProperty( "SelectionNamespaces" , svNamespace );
oDoc.load( svFile );
if ( oDoc.parseError.errorCode != 0 ) then
NumToStr ( svError , oDoc.parseError.errorCode );
NumToStr ( svLine , oDoc.parseError.line );
NumToStr ( svLinePos , oDoc.parseError.linepos );
MessageBox ( "The XML File did not load correctly.\n" +
"Error Code: " + svError + "\n" +
"Error Line: " + svLine + "\n" +
"Error Line Position: " + svLinePos + "\n" +
oDoc.parseError.reason , 0 );
return 1;
endif;

//Search XML File for all matching elements
set oNodeList = oDoc.selectNodes( svXpath );

//If no matching elements
if ( oNodeList.length = 0 ) then
MessageBox( "No matching elements found." , 0 );
return 1;
endif;

//If more than one matching elements
if ( oNodeList.length > 1 ) then
svMessage = "There is more than one matching element. Press YES to accept changing all nodes or NO to quit";
if ( AskYesNo ( svMessage , YES ) = 0 ) then
return 1;
endif;
endif;

//Change attribute for all matching elements
for i = 0 to ( oNodeList.length - 1 );
set oNode = oNodeList.nextNode;
try
oNode.attributes.getNamedItem( svAttribute ).value = svValue;
catch
nFailed = nFailed + 1;
endcatch;
endfor;

oDoc.save( svFile );
set oDoc = NOTHING;
set oNode = NOTHING;
set oNodeList = NOTHING;

return nFailed;

end;[/CODE]
0 Kudos
Miroslav
Level 2

this posts above helped me a lot...
0 Kudos
TimStVCS
Level 7

While I appreciate all of the examples, this is a horrible piece of functionality in InstallShield. I don't want to have to resort to these measures to do what should be a "simple" update to an existing .xml file. I am not an XML programmer, nor do I want to be - that is why we spend thousands of dollars on a tool like InstallShield that is supposed to do these things for us. Extremely disappointed in this functionality, or lack thereof.

Tim
0 Kudos
cspanellis
Level 3

Where are you declaring variables such as m_strDBDataSource? I would take it we need access to variables set by the SQL dialog (i.e. IS_SQLSERVER_SERVER, IS_SQLSERVER_USERNAME, etc.)

Thanks
0 Kudos
rootme
Level 4

Hi,

If my XML file begins like this:





4
*
1935
..........


And I need to replace IpAdress and Port value.
What would be the value of svXpath ?

Thanks,
Bianca
0 Kudos
cspanellis
Level 3

Just add your config/xml file in the XML file editor, and then you'll see those elements pop up. After you load the document, on the element work area on the right there will be a tab/section where you can replace those fields with properties from your project.
0 Kudos
rootme
Level 4

Hi,

The XML files I need to handle don't belong to my install package, but to an already installed application to which I need to add some elements and replace some values of current elements.

The XML Import menu in IS is not handling files from other applications right ?

Thanks for you time,
Bianca

cspanellis wrote:
Just add your config/xml file in the XML file editor, and then you'll see those elements pop up. After you load the document, on the element work area on the right there will be a tab/section where you can replace those fields with properties from your project.
0 Kudos
rootme
Level 4

I call the function like this:


svFile = appapath ^ "\\conf\\$VHost.xml";
svXpath ="//Root/VHost/HostPortList/HostPort/IpAddress";
svAttribute = "*";
svValue = "${BindAddress}";
ModifyXmlAttribute( svFile , 0 , "" , svXpath , svAttribute , svValue );


And nothing is updated in the file. I don;t know if svXpath is defined correctly.

My file is :






4
*
1935






Also I need to add new elements in the file. For this I found no solution.

Thanks,
Bianca
0 Kudos
cspanellis
Level 3

I think you can modify any file, whether it's in your project or not. You may just have to specify the proper location to match where it will be. It actually gives you an option to create the file if it doesn't exist so I'm pretty sure you can modify any file.
0 Kudos
rootme
Level 4

No you can't. I imported the XML file from it's location c:\Program Files\.... and during installation IS creates the file in my application install dir.

Bianca

cspanellis wrote:
I think you can modify any file, whether it's in your project or not. You may just have to specify the proper location to match where it will be. It actually gives you an option to create the file if it doesn't exist so I'm pretty sure you can modify any file.
0 Kudos
another_1
Level 4

Unfortunately, this piece of code is not doing anything in case when a namespace defined... Any advice?
jcouvret wrote:
I started with the script provided by The Traveler, however I was needing to edit a somewhat complicated XML file created by a different software package that included a default namespace and was failing the DTD Schema verification. I got around this by figuring out how to define the namespace(s) to search under in XPath and using an older version of DOM that didn't do the DTD verification. Here is the code with explanation if it can help anyone else avoid several days of learning about XPath and namespaces.

[CODE]prototype ModifyXmlAttribute( STRING , NUMBER , STRING , STRING , STRING , STRING );

/*////////////////////////////////////////////////////////////////////////////////////
function ModifyXmlAttribute

Description: This function changes the value of an attribute associated with
one or more elements defined by an Xpath statement. If there are
multiple elements matching the Xpath statement, this function will
offer to change the attributes of all matching elements, or abort.

Inputs: svFile = The full path to the XML file to modify.
nNamespace = 1 to use namespace in search, 0 to not use namespace.
svNamespace = Only used if nNamespace = 1. This the namespace to be used
in the Xpath search string. If not used, enter "" for value.
svXpath = The Xpath statement that defines the element(s) containing the
attribute to be modified.
svAttribute = The name of the attribute to be modified.
svValue = The value to be written to the specified attribute.

Return: 0 - The attributes of all matching elements were successfully changed.
Greater than 0 - Some or all attribute changes failed.

Example:
XML File:













Function Variables:
svFile = "Path\\to\\your\\file.xml"
nNamespace = 1
svNamespace = "xmlns:pro='http://deltabis.com/products' xmlns:itin='http://deltabis.com/itinerary'"
svXpath = "//pro:lists/pro:product[@type='tshirt']/itin:itinerary"
svAttribute = "sold"
svValue = "1000"

Result:
Before:
After:

Notes: If a default namespace is defined (xmlns=something) in the XML file, that
namespace will have to be defined or the Xpath search will not return any
elements. For more information, go to http://www.xml.com/lpt/a/979
*////////////////////////////////////////////////////////////////////////////////////

function ModifyXmlAttribute( svFile , nNamespace , svNamespace , svXpath , svAttribute , svValue )
OBJECT oDoc, oNode, oNodeList, oDocType;
STRING svMessage, svError, svLine, svLinePos;
NUMBER i, nFailed;
begin

nFailed = 0;

// Check to see if the file exists...
if Is( FILE_EXISTS , svFile ) = FALSE then
MessageBox("XML file does not exist.",0);
return 1;
endif;

//Set XML DOM Object
set oDoc = CreateObject( "Microsoft.XMLDOM" );
if ( IsObject( oDoc ) = FALSE ) then
MessageBox( "MSXML DOM-Document Connection Failed" , 0 );
return 1;
endif;
oDoc.async = FALSE;

//Set namespace and load file
oDoc.setProperty( "SelectionLanguage" , "XPath" );
oDoc.setProperty( "SelectionNamespaces" , svNamespace );
oDoc.load( svFile );
if ( oDoc.parseError.errorCode != 0 ) then
NumToStr ( svError , oDoc.parseError.errorCode );
NumToStr ( svLine , oDoc.parseError.line );
NumToStr ( svLinePos , oDoc.parseError.linepos );
MessageBox ( "The XML File did not load correctly.\n" +
"Error Code: " + svError + "\n" +
"Error Line: " + svLine + "\n" +
"Error Line Position: " + svLinePos + "\n" +
oDoc.parseError.reason , 0 );
return 1;
endif;

//Search XML File for all matching elements
set oNodeList = oDoc.selectNodes( svXpath );

//If no matching elements
if ( oNodeList.length = 0 ) then
MessageBox( "No matching elements found." , 0 );
return 1;
endif;

//If more than one matching elements
if ( oNodeList.length > 1 ) then
svMessage = "There is more than one matching element. Press YES to accept changing all nodes or NO to quit";
if ( AskYesNo ( svMessage , YES ) = 0 ) then
return 1;
endif;
endif;

//Change attribute for all matching elements
for i = 0 to ( oNodeList.length - 1 );
set oNode = oNodeList.nextNode;
try
oNode.attributes.getNamedItem( svAttribute ).value = svValue;
catch
nFailed = nFailed + 1;
endcatch;
endfor;

oDoc.save( svFile );
set oDoc = NOTHING;
set oNode = NOTHING;
set oNodeList = NOTHING;

return nFailed;

end;[/CODE]
0 Kudos
another_1
Level 4

another_1 wrote:
Unfortunately, this piece of code is not doing anything in case when a namespace defined... Any advice?

Nevermind, figured out how to use it!
It is all in how you set your variables.
0 Kudos