cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Sairen
Level 7

Adding and Updating XML

This has been making me crazy. I really hope someone can help.

I have an XML doc in this format:



First
localhost
6000
RememberLast

Development


Second
127.0.0.1
6000
RememberLast

Test



There could be any number of these Profiles.

In the UI, I prompt for the value in profile name [PROFILENAME], the host name [HOSTNAME] and the port [HOSTPORT].
I'd like to create a new Profile block if and only if the provided PROFILENAME does not match an existing field. If it does, I want that block updated. I've tinkered with a whole bunch of XPath on the Profile tag level, but I only manage to get either
- There's just one Profile block and it's always overwritten
OR
- I potentially have a new block with the same name created every time the installer runs. 😛

Can someone help me figure out what queries and properties I need to set on which tags in the XML Changes View??

Thanks in advance.
Labels (1)
0 Kudos
(8) Replies
MichaelU
Level 12 Flexeran
Level 12 Flexeran

As some very general guidance, a major part of the trick is setting up your XPath conditions to check for exactly what you need. In this case, it might be something like /ConnectionProfiles/Profile[Name='First'] (if I've got my XPath notation right; normally it takes me a few tries). I'm not quite savvy on how we handle the square brackets here if you want to include a property reference, so things might go badly if you try to make this /ConnectionProfiles/Profile[\[]Name='[NAMEPROP]'[\]]. So test a hardcoded case first until you know the XPath is correct, then see if you can substitute properties in.
0 Kudos
Sairen
Level 7

Thanks for the tip, Michael. I wasn't sure how it was handling the square brackets and I didn't know about that with the escape sequences.

One of the other problems I'm running into seems to be something along these lines...

I tell the profile tag to look for "the one where name is First" and if not found, create it. It does that much.
But then the children tags go... so there's a say... HostName whose parent is a Profile tag that has a child where Name contains First. That's not found. However, as it says in documentation, the "create if not found" doesn't go through generations. so no HostName is created.

It's like I need to create the Profile tag AND the child Name / First at the same time. Any suggestions?
0 Kudos
MichaelU
Level 12 Flexeran
Level 12 Flexeran

Watch the XPaths that get created and checked - I think these show up in the verbose log. Ignoring the property substition aspect for clarity, ensure that when your child elements are being assessed they look for /ConnectionProfiles/Profile[Name='First']/HostName instead of just /ConnectionProfiles/Profile/HostName. The latter will match on any Profile element, whereas the former will limit it to one matching the specified condition. (My example may still show an incorrect condition for what you want.)
0 Kudos
Sairen
Level 7

Michael, can you explain the syntax of your bracket escape sequences?

I would expect something like
/ConnectionProfiles/Profile[Name='\[NAMEPROP\]']
But you have a lot more going on there and I'm afraid I can't parse it nor can I find it in the help documentation.

What I was running into is that once a parent wasn't found (and was subsequently created), children of the parent that wasn't found would not be created, so I put the query at child level and came up with this monstrosity

InstallShield 15:51:34: Processing XPath '//Profile/*[contains(.,'From Wizard')]/../DefaultUsername'
InstallShield 15:51:34: XPath '//Profile/*[contains(.,'From Wizard')]/../DefaultUsername' not found, creating

It says it's creating, but it never does. Where I stand now is that it will overwrite a block whose name is "From Wizard" (good start!) but never creates a new block.

I could use some real hand-holding here, I'm afraid, if anyone's a whiz with the XML Changes view or XPath...
0 Kudos
MichaelU
Level 12 Flexeran
Level 12 Flexeran

The quoting I used is standard MSI escaping. Namely the sequence [\c] (where c can be any character) is replaced by just that character. So [\[] becomes [ and [\]] becomes ]. After that it's just a matter of getting the XPath correct, and that's where I'm a little weak. I can't remember the XPath for matching against element content.

Some quick searches suggest the XPath should be either //Elt[.='blah'] or //Elt[text()='blah'], so with property NAMEPROP and escaping back in, it would look something like //Profile[\[].='[NAMEPROP]'[\]]/...
0 Kudos
Sairen
Level 7

(well, I was hoping this would go away, but it didn't...)

Michael, I got my query down using a hard-coded value, and it's pretty swell. Can you (or anyone else reading this) confirm for me, though, that this escaping and using a property thing in the query actually... well, WORKS? I'm not having any luck at all with it.

Here's what I've got in the log:

InstallShield 15:31:15: Processing XPath '//Profile[\[]Name='[IN_HOSTNAME]'[\]]'
InstallShield 15:31:15: XPath '//Profile[\[]Name='[IN_HOSTNAME]'[\]]' not found, creating
InstallShield 15:31:15: Creating element: Name=Profile, Namespace=
This works

InstallShield 15:31:15: Processing XPath '//Profile[\[]Name='[IN_HOSTNAME]'[\]]/Name[\[].='[IN_HOSTNAME]'[\]]'
InstallShield 15:31:15: XPath '//Profile[\[]Name='[IN_HOSTNAME]'[\]]/Name[\[].='[IN_HOSTNAME]'[\]]' not found, creating
InstallShield 15:43:57: Checking XPath 'Profile[\[]Name='[IN_HOSTNAME]'[\]]'
Notice here that there's no actual "creating element" here. Then it goes on to processing the next item.

It doesn't seem to me to be processing the property name "IN_HOSTNAME" correctly, and it doesn't create that Name node or anything after it.


TIA.
0 Kudos
MichaelU
Level 12 Flexeran
Level 12 Flexeran

I got a spare minute to look at the code, and per the log message you see, that's the literal XPath that gets queried. There's no MSI formatting applied there. I've filed IOA-000068605 to request this. In the meantime, you might consider the text file changes view if your changes are simple enough, or coding against an XML API such as MSXML in InstallScript or your preferred language.
0 Kudos
Sairen
Level 7

Thanks for confirming that, Michael.

I did eventually give up and just code the stupid thing in VBScript using the XML DOM. Using that approach, the whole thing took less than 3 hours... Go figure.
0 Kudos