Old 28th September 2005, 18:52   #1
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
XML plugin

XML plugin parses an XML document, and builds from that a Document Object Model (DOM) that can be read, modified and saved. XML plugin is based on TinyXml (2.4.0 RC).

Features:
- Read and/or modified xml files
- Code is fast and lightweight
- Unicode UTF-8 support
- "MSXML.DLL" independent
- Support for condense and non-condense white spaces
- Row and Column tracking


"XML" plugin v1.0
Attached Files
File Type: zip xml.zip (57.4 KB, 2142 views)
Instructor is offline   Reply With Quote
Old 29th September 2005, 08:17   #2
kike_velez
Member
 
Join Date: Jun 2004
Location: Barcelona
Posts: 57
for

PHP Code:
"MSXML.DLL" independent 
Best Regards and Good Job
kike_velez is offline   Reply With Quote
Old 20th October 2005, 16:49   #3
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Changes:
- TinyXml updated to v2.4.1
- Fixed: output variable in xml::NoChildren
- New: xml::GetText
   Convenience function for easy access to the text inside current element.
- New: xml::SetCDATA
   Turns on or off a CDATA representation of the current element text.
- New: xml::IsCDATA
   Queries whether this represents text using a CDATA section.


"XML" plugin v1.1
Attached Files
File Type: zip xml.zip (59.5 KB, 1235 views)
Instructor is offline   Reply With Quote
Old 20th October 2005, 18:58   #4
Comm@nder21
Major Dude
 
Join Date: Jul 2003
Location: germany, b-w
Posts: 734
Send a message via ICQ to Comm@nder21
next plugin i repack for correct usage of nsis file structure
Attached Files
File Type: zip plugin_xml.zip (58.4 KB, 1266 views)
Comm@nder21 is offline   Reply With Quote
Old 25th October 2005, 04:23   #5
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
-TinyXml updated to v2.4.2
-Fixed: "CreateNode" appearance of the "\r\n" at the end (thanks Lee Thomason)
-Fixed: Now error appears if current node is TEXT and uses "InsertEndChild"
-Changed: "AttributeByName" -> "GetAttribute" now not only returns value of the attribute, but also goes to it
-New: "GetNodeValue" can be useful in some cases


"XML" plugin v1.2
Attached Files
File Type: zip xml.zip (59.7 KB, 1166 views)
Instructor is offline   Reply With Quote
Old 7th November 2005, 17:58   #6
false
Junior Member
 
Join Date: Nov 2005
Location: Oakville, Ontario, Canada
Posts: 3
How would I go about selecting a particular node by it's name? Like how Olivier Marcoux's NSIS XML uses...

nsisXML::select <XPath expression>

Thx!
false is offline   Reply With Quote
Old 7th November 2005, 18:35   #7
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
If you want to "select" the node you need go to it (FirstChildElement, NextSiblingElement ...). Easy for me, when you ask the concrete example, what you trying to do.
Instructor is offline   Reply With Quote
Old 7th November 2005, 20:59   #8
false
Junior Member
 
Join Date: Nov 2005
Location: Oakville, Ontario, Canada
Posts: 3
Somewhere nested in my XML, I have a set of child nodes who have the same name and share the same parent. The child nodes differ by having different attributes values.

I would like to test if a particular node exists in an XML without having to drill down using FirstChildElement and NextSiblingElement. If the node with the target node name exists, I would make it the current node.

I thought GotoHandle would do this for me but I am wrong in thinking it takes in a node name for a parameter.
false is offline   Reply With Quote
Old 7th November 2005, 21:33   #9
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
I'll think about recursive node search
Instructor is offline   Reply With Quote
Old 9th November 2005, 15:45   #10
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
New: [xml::FindNextElement /NOUNLOAD "[name]" .r0 .r1]
&nbsp;&nbsp;&nbsp;-Search for element (recursive), returns the element name and goes to it.
New: [xml::FindCloseElement /NOUNLOAD]
&nbsp;&nbsp;&nbsp;-Closes search opened by xml::FindNextElement.
New: [xml::ElementPath /NOUNLOAD .r0]
&nbsp;&nbsp;&nbsp;-Returns the current element path.
&nbsp;&nbsp;&nbsp;(e.g. "/a/b/c[3]/d")
New: [xml::GotoPath /NOUNLOAD "[path]" .r0]
&nbsp;&nbsp;&nbsp;-Goes to the specified path.
&nbsp;&nbsp;&nbsp;(e.g. from root "/a/b[2]/c/d", from current element "a/b[2]/c/d",
&nbsp;&nbsp;&nbsp;&nbsp;using last element 'b' "a/b[-1]/c/d")


"XML" plugin v1.3
Attached Files
File Type: zip xml.zip (66.1 KB, 1028 views)

Last edited by Instructor; 9th November 2005 at 17:43.
Instructor is offline   Reply With Quote
Old 9th November 2005, 15:56   #11
false
Junior Member
 
Join Date: Nov 2005
Location: Oakville, Ontario, Canada
Posts: 3
You da man! That was a fast. I'll give this a shot. Thx
false is offline   Reply With Quote
Old 9th November 2005, 18:33   #12
rsegal
Senior Member
 
rsegal's Avatar
 
Join Date: Feb 2003
Location: Toronto, Canada
Posts: 227
Hey Instructor any plans for UTF-16 support? I could really use that.
rsegal is offline   Reply With Quote
Old 9th November 2005, 19:15   #13
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
DOM builds by TinyXML parser, so UTF-16 is depend on this project. BTW: Where is already have feature request about it.
Instructor is offline   Reply With Quote
Old 9th November 2005, 20:01   #14
rsegal
Senior Member
 
rsegal's Avatar
 
Join Date: Feb 2003
Location: Toronto, Canada
Posts: 227
Ah excellent. Good to know it's on the queue.
rsegal is offline   Reply With Quote
Old 10th November 2005, 14:04   #15
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Added: now "GotoPath" can accept elements without name (e.g. using any last element "a/[-1]/c/d")


"XML" plugin v1.4
Attached Files
File Type: zip xml.zip (66.1 KB, 1085 views)
Instructor is offline   Reply With Quote
Old 10th December 2005, 16:21   #16
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Fixed: Now "ElementPath" and "GotoPath" correctly working with the document beginning. If "ElementPath" returns "" - the current element is the beginning of the document. [xml::GotoPath /NOUNLOAD "" .r0] - go to the document beginning.


"XML" plugin v1.5
Attached Files
File Type: zip xml.zip (66.3 KB, 1028 views)
Instructor is offline   Reply With Quote
Old 13th January 2006, 10:04   #17
Kiggie
Guest
 
Posts: n/a
Bug in GetAttribute

Hi,

there seems to be a bug in the GetAttribute Method, it returns
always -1 for the first attribute of a node.

A possible workaround is to check if the FirstAttribute differs from the desired attribute.

Kind Regards,

Rob
  Reply With Quote
Old 13th January 2006, 10:46   #18
chagam
Junior Member
 
Join Date: Jan 2006
Posts: 2
Hi,

May be I'm missing something but I don't understand how to replace a text value.

There's a xml::GetText function. How do I do a xml::SetText ?

Thanks in advance

Chag
chagam is offline   Reply With Quote
Old 13th January 2006, 10:54   #19
Kiggie
Guest
 
Posts: n/a
Question

Quote:
Originally posted by chagam
Hi,

May be I'm missing something but I don't understand how to replace a text value.

There's a xml::GetText function. How do I do a xml::SetText ?

Thanks in advance

Chag
Did you try the xml::SetNodeValue method ?
  Reply With Quote
Old 13th January 2006, 11:25   #20
chagam
Junior Member
 
Join Date: Jan 2006
Posts: 2
Hi,

Yes, I tried. May be a did something wrong.

My xml file looks like this :
<config>
<local>
<host>test</host>
</local>
</config>

I tried :
xml::GotoPath /NOUNLOAD "/config/local/host" .r0
xml::SetNodeValue /NOUNLOAD "1234" .r0

and my new xml file looks like this :
<config>
<local>1234
</local>
</config>

Chag
chagam is offline   Reply With Quote
Old 13th January 2006, 12:26   #21
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
code:
Name "XMLTest"
OutFile "XMLTest.exe"

Section
xml::LoadFile /NOUNLOAD "test.xml" .r0
MessageBox MB_OK "xml::LoadFile$\n$$0=$0"

xml::GotoPath /NOUNLOAD "/config/local/host" .r0
MessageBox MB_OK "xml::GotoPath$\n$$0=$0"

xml::FirstChild /NOUNLOAD "" .r0 .r1
MessageBox MB_OK "xml::FirstChild$\n$$0=$0$\n$$1=$1"

xml::SetNodeValue /NOUNLOAD "1234"
MessageBox MB_OK "xml::SetNodeValue"

xml::SaveFile "test_saved.xml" .r0
MessageBox MB_OK "xml::SaveFile$\n$$0=$0"
SectionEnd

Instructor is offline   Reply With Quote
Old 13th January 2006, 12:31   #22
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Quote:
there seems to be a bug in the GetAttribute Method, it returns
always -1 for the first attribute of a node.
Fixed, thanks.

Last edited by Instructor; 13th January 2006 at 13:36.
Instructor is offline   Reply With Quote
Old 13th January 2006, 13:40   #23
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Fixed: GetAttribute returns -1 for the first attribute.
New: "SetText" -convenience function for easy set the text of the current element.


"XML" plugin v1.6
Attached Files
File Type: zip xml.zip (66.4 KB, 1031 views)

Last edited by Instructor; 13th January 2006 at 14:24.
Instructor is offline   Reply With Quote
Old 3rd March 2006, 12:32   #24
xilay
Junior Member
 
Join Date: Aug 2005
Posts: 29
Hello,

I need to create a new element without text.
I use this code :
PHP Code:
xml::LoadFile /NOUNLOAD "test.xml" .r0
xml
::GotoPath /NOUNLOAD "/root" .r0
xml
::CreateNode /NOUNLOAD "<histo></histo>" .r0
xml
::InsertEndChild /NOUNLOAD "$0" .r0
xml
::SaveFile /NOUNLOAD "test.xml" .r0 
But the new element is with a blank at the end, like this :
PHP Code:
<root>
    <
histo />
</
root
If I create the element with text, it's ok.
Have you got an idea?

Thanks

(sorry if my english is not very good)
xilay is offline   Reply With Quote
Old 3rd March 2006, 14:13   #25
Comm@nder21
Major Dude
 
Join Date: Jul 2003
Location: germany, b-w
Posts: 734
Send a message via ICQ to Comm@nder21
this is correct xml behaviour.
empty elements have to be <element />, not <element></element>.

last one is no valid xml!
Comm@nder21 is offline   Reply With Quote
Old 3rd March 2006, 15:10   #26
xilay
Junior Member
 
Join Date: Aug 2005
Posts: 29
Yes, I know, the problem is the blank after 'histo'.
I have this <histo /> (you see, the blank between 'histo' and '/') and not this <histo/>.

Sorry for my bad explanation
xilay is offline   Reply With Quote
Old 3rd March 2006, 19:16   #27
Comperio
Major Dude
 
Comperio's Avatar
 
Join Date: Jan 2005
Location: Oregon Coast
Posts: 737
W3.org (which pretty much has the final word on markup languages like XML) recommends that a space should be used when declaring empty tags.

So this would be proper XML:
<histo />

NOT this:
<histo/>

See the section tags for empty elements at http://www.w3.org/TR/REC-xml/#sec-starttags for more info.

[edit]
And FWIW, I've always seen empty tags written using a space between the element name and the '/' character...
Comperio is offline   Reply With Quote
Old 6th March 2006, 07:10   #28
xilay
Junior Member
 
Join Date: Aug 2005
Posts: 29
Ok, I use xmlspy and it deletes the blank, so, I thought it was not normal.
Thanks a lot (and thanks for this perfect plugin)
xilay is offline   Reply With Quote
Old 6th March 2006, 12:50   #29
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Updated: TinyXml to v2.4.3
Changed: Now plugin used header "XML.nsh" for custom user variables and
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;better compile errors check.

Update from previous versions:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Insert line in script:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;!include "XML.nsh"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Replace:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xml::LoadFile -> ${xml::LoadFile} ...
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Replace:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.r0 -> $0, .r1 -> $1 ... .R0 -> $R0, .R1 -> $R1 ...

"XML" plugin v1.7
Attached Files
File Type: zip xml.zip (78.2 KB, 1336 views)
Instructor is offline   Reply With Quote
Old 3rd May 2006, 13:52   #30
stwhit
Junior Member
 
Join Date: Mar 2006
Posts: 2
I need to be able to parse two XML documents at the same time (because I'm merging them during an upgrade process).

From looking at the API and the source code, it looks like this XML plugin only supports working on a single XML document at a time, because there is no concept of a file handle being returned by ${xml::LoadFile} and being passed to the other functions. It looks like there is a single, global XML document being edited (TiXmlDocument doc).

So, two questions:

1. Is it possible to edit two XML documents at the same time using this plugin?
2. If not, would you consider enhancing the plugin to use file handles to support editing multiple XML documents at once?

Thanks!
stwhit is offline   Reply With Quote
Old 3rd May 2006, 14:19   #31
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
1. Not.
2. I'm not plaining this.

But you can use ${xml::CloneNode}

code:

Section
${xml::LoadFile} "file.xml" $0
MessageBox MB_OK "xml::LoadFile$\n$$0=$0"

${xml::GotoPath} "/" $0
MessageBox MB_OK "xml::GotoPath$\n$$0=$0"

${xml::CloneNode} $R0
MessageBox MB_OK "xml::CloneNode$\n$$R0=$R0"

${xml::Unload}


${xml::LoadFile} "file2.xml" $0
MessageBox MB_OK "xml::LoadFile$\n$$0=$0"

${xml::GotoPath} "/" $0
MessageBox MB_OK "xml::GotoPath$\n$$0=$0"

${xml::InsertBeforeNode} "$R0" $0
MessageBox MB_OK "xml::InsertBeforeNode$\n$$0=$0"

${xml::FreeNode} "$R0" $0
MessageBox MB_OK "xml::FreeNode$\n$$0=$0"

${xml::SaveFile} "file2.xml" $0
MessageBox MB_OK "xml::SaveFile$\n$$0=$0"

${xml::Unload}
SectionEnd

Instructor is offline   Reply With Quote
Old 31st July 2006, 02:48   #32
Comperio
Major Dude
 
Comperio's Avatar
 
Join Date: Jan 2005
Location: Oregon Coast
Posts: 737
I'm trying to create an XML file from scratch using this plugin. Is this possible? If so, can someone post an example of how I might accomplish this?

Last edited by Comperio; 31st July 2006 at 03:45.
Comperio is offline   Reply With Quote
Old 31st July 2006, 14:56   #33
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
FileWrite
Instructor is offline   Reply With Quote
Old 31st July 2006, 23:48   #34
Comperio
Major Dude
 
Comperio's Avatar
 
Join Date: Jan 2005
Location: Oregon Coast
Posts: 737
darn...
I was hoping that I could build an XML file in memory using the plugin and then output the whole thing to a file. (It would be a cool enhancement for sure.)

I guess for now, I'll just write my own FileWrite functions to get me by for now.

Thanks for the feedback!
Comperio is offline   Reply With Quote
Old 16th August 2006, 06:00   #35
emmett_m
Junior Member
 
Join Date: Aug 2006
Posts: 4
Hi, I am hoping you can help me, I tried some of the code examples found in \NSIS\Examples\XMLXMLTest.nsi. And tried to apply these examples with what I want with little success, here is what I am trying to achieve.

I have the following xml file (VS.Net config file):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>

<appSettings>
<add key="somekey" value="some value"/>
</appSettings>

<connectionStrings>
<add name="ConnString" connectionString="TRYING TO MODIFY THIS TEXT"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>


When the installer runs, I am trying to change the text in the connectionString attribute of the <add> element. I have placed the file in the same directory as my install script, and the script includes the following code:

!include "XML.nsh"

var /global ReplacementString
var /global fhandle

${xml::LoadFile} "appname.exe.config" $fhandle
MessageBox MB_OK "$fhandle" ; always returns -1

${xml::GotoPath} "/configuration/connectionStrings/add" $fhandle
${xml::SetAttribute} "connectionString" "$ReplacementString" $fhandle
${xml::SaveFile} "$INSTDIR\appname.exe.config" $fhandle
${xml::Unload} ; unload plugin

When attempting to open the file it always returns -1, can anybody tell me what the obvious mistake that I am making, and yes the file is in UTF8 format, I have however tried saving the format of the file from Notepad, into different formats in desperation, with no help (as I expected).

Last edited by emmett_m; 16th August 2006 at 06:32.
emmett_m is offline   Reply With Quote
Old 16th August 2006, 07:17   #36
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
I have no problem. Make sure that the file exist and try to specify full path to it.
Instructor is offline   Reply With Quote
Old 16th August 2006, 08:00   #37
emmett_m
Junior Member
 
Join Date: Aug 2006
Posts: 4
That is interesting, I tried as you suggested to supply the full path to the file, which is the same location as the setup program, and it works. However I thought when you specified a file like:

${xml::LoadFile} "appname.exe.config" $fhandle

That it would use the file from the same directory as the installer, it would seem not. Also I tried the following:

${xml::LoadFile} "$EXEDIR\appname.exe.config" $fhandle

Which seems to be what I should have done. Thanks for your time ;-)
emmett_m is offline   Reply With Quote
Old 17th August 2006, 17:47   #38
Comm@nder21
Major Dude
 
Join Date: Jul 2003
Location: germany, b-w
Posts: 734
Send a message via ICQ to Comm@nder21
as the plugin is extracted to $PLUGINSDIR i guess it searches the file there, not in $EXEDIR.
Comm@nder21 is offline   Reply With Quote
Old 17th August 2006, 23:59   #39
emmett_m
Junior Member
 
Join Date: Aug 2006
Posts: 4
Just in case somebody else comes across this problem, what I really wanted to do was have the .config file wrapped up into the installer, and manipulate that version, to do this I did the following:

Section "MainSection" SEC01
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
File "appname.exe.config" ; reads file into memory and wraps(compresses) into installer
Section

${xml::LoadFile} "appname.exe.config" $fhandle ; modify the config file compressed in installer


This seems to work great.
emmett_m is offline   Reply With Quote
Old 24th August 2006, 21:49   #40
JDaniels13
Junior Member
 
Join Date: Aug 2006
Location: Olympia WA
Posts: 4
I recently needed to edit existing .NET (Framework 1.1) config files within an NSIS install. Using some of the info here and the XML plugin docs, I was able to put something together that actually appears to work for changing keys in .NET 1.1 config files. Below is what I came up with. (There are some extra message boxes for debugging that should be removed prior to using.) Is there an easier way??!! I was truly surprised at the lack of discussion of this topic. I didn't want to write a .NET program in C# or VB.NET because I wanted it all to be in the NSIS setup, for simplicity's sake.


!include "XML.nsh"

var /global IOResult
var /global NewNodeHandle
var /global CurrentValue
var /global ElementName

!macro EditDotNETConfigFile ConfigFile KeyPath KeyName KeyValue
${xml::LoadFile} ${ConfigFile} $IOResult
${xml::GotoPath} ${KeyPath} $IOResult
IntCmp $IOResult 0 pathLookupSucceeded noAppSettings
pathLookupSucceeded:
MessageBox MB_OK "pathLookupSucceeded for ${KeyPath}"
checkAttributeExistence:
${xml::GetAttribute} "key" $CurrentValue $IOResult
; Did we find an existing instance of our config setting?
IntCmp $IOResult 0 checkKeyAttributeValue toNextElement
checkKeyAttributeValue:
MessageBox MB_OK "checkKeyAttributeValue current value is $CurrentValue vs desired key ${KeyName}"
; OK, found one, is it our desired key? Case-sensitive compare.
StrCmpS $CurrentValue ${KeyName} foundKeyAttribute toNextElement
toNextElement:
MessageBox MB_OK "checkKeyAttributeValue $CurrentValue didn't match ${KeyName}"
; Didn't find the <add key= " attribute name we wanted, check next "<add " element
${xml::NextSiblingElement} "add" $ElementName $IOResult
MessageBox MB_OK "toNextElement name is $ElementName IOResult is $IOResult"
IntCmp $IOResult 0 checkAttributeExistence noExistingEntry

foundKeyAttribute:
${xml::GetAttribute} "value" $CurrentValue $IOResult
MessageBox MB_OK "foundKeyAttribute check value attribute $CurrentValue vs desired key ${KeyValue}"
; Did we find an existing instance of our config setting?
StrCmp $CurrentValue ${KeyValue} valueUnchanged valueChanged
valueChanged:
${xml::SetAttribute} "value" "${KeyValue}" $IOResult
IntCmp $IOResult 0 setAttributeWorked setAttributeFailed
setAttributeWorked:
goto saveConfigFile

noExistingEntry:
MessageBox MB_OK "GetAttribute could not find existing value for ${KeyName}"
${xml::CreateNode} '<add key="${KeyName}" value="${KeyValue}" />' $NewNodeHandle
${xml::InsertAfterNode} $NewNodeHandle $IOResult
goto saveConfigFile
setAttributeFailed:
MessageBox MB_OK "SetAtribute failed for ${KeyName}"
goto cleanUp
noAppSettings:
MessageBox MB_OK "XPath not resolved for ${KeyPath}"
goto cleanUp
saveConfigFile:
${xml::SaveFile} ${ConfigFile} $IOResult
valueUnchanged:
; Just fall thru and unload
cleanUp:
${xml::Unload} ; unload plugin
!macroend

; Called as follows:

!insertmacro EditDotNETConfigFile "c:\InetPub\wwwroot\MyWebSite\Web.config" "configuration/appSettings/add" "connectionString" "MyTestConnString1a"


P.S. I tried the nsisXML plugin but it wanted to do "extra" things to the tags in the .NET config files, so I came back to this XML plugin and it's what I got to work first.
JDaniels13 is offline   Reply With Quote
Reply
Go Back   Winamp & SHOUTcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump