Old 24th August 2006, 21:58   #41
JDaniels13
Junior Member
 
Join Date: Aug 2006
Location: Olympia WA
Posts: 4
A .NET 1.1 config file used in testing

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="@CBR_CBRFILE" value="Initialization.cbr" />
<!-- Environment Setup Type should be "PROD" or "DEV" or "QA" -->
<add key="Site.Environment" value="QA" />
<!-- Environment Setup End -->
<!-- Security Setup -->
<add key="ConnectionString" value="Case sensitive, shouldn't match this" />
<!--Socket Setup (used for refund transaction) -->
<!--add key="SocketPort" value="3805" / -->
<!--add key="SocketTimeout" value="30000" / -->
</appSettings>
</configuration>

So after calling the macro, the file would be like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="@CBR_CBRFILE" value="Initialization.cbr" />
<!-- Environment Setup Type should be "PROD" or "DEV" or "QA" -->
<add key="Site.Environment" value="QA" />
<!-- Environment Setup End -->
<!-- Security Setup -->
<add key="ConnectionString" value="Case sensitive, shouldn't match this" />
<add key="connectionString" value="This is the one that should get matched and changed" />
<!--Socket Setup (used for refund transaction) -->
<!--add key="SocketPort" value="3805" / -->
<!--add key="SocketTimeout" value="30000" / -->
</appSettings>
</configuration>


The problem with .NET config files is that all the elements in the appsettings section are "<add ", so you have to then navigate through each element looking for the attributes "key", to find the node you want, and then once you find it, set the "value" attribute for that node. Thus all the code for navigating within the duplicate-named "<add " elements.

If someone has an easier way, please share it! I didn't see an NSIS plugin for .NET config file editing, is there one I missed?
JDaniels13 is offline   Reply With Quote
Old 24th August 2006, 22:41   #42
JDaniels13
Junior Member
 
Join Date: Aug 2006
Location: Olympia WA
Posts: 4
The thing that the nsisXML has going for it is it supports XPath, including the attribute specs in the XPath query. I understand there is a Tiny XPath company to TinyXML, but the XPath functionality is not integrated into the XML plugin.

Here's what I had for the nsisXML plugin version of the .NET 1.1 config file editing macro:

!macro EditDotNETConfigFile2 ConfigFile KeyXPath KeyName KeyValue
SetPluginUnload alwaysoff
nsisXML::create
nsisXML::load ${ConfigFile}
nsisXML::select ${KeyXPath} /* '/main/child[@attrib="value2"]' */
IntCmp $2 0 notFound
; nsisXML::removeChild
nsisXML::createElement "add"
nsisXML::setText " "
nsisXML::appendChild
nsisXML::getAttribute ${KeyName}
DetailPrint "Attribute ${KeyName} is $3"
nsisXML::setAttribute "key" ${KeyName}
nsisXML::setAttribute "value" ${KeyValue}
MessageBox MB_OK "attribute set"
SetPluginUnload manual
nsisXML::save ${ConfigFile}
Goto end
notFound:
MessageBox MB_OK "XPath not resolved"
DetailPrint "XPath not resolved"
end:
!macroend

; Called like this:
!insertmacro EditDotNETConfigFile2 "c:\InetPub\wwwroot\MyWebSite\Web2.config" '/configuration/appSettings/add[@key="connectionString"]' "connectionString" "TestConnString2"

It was very handy to use XPath to go right to the "<add " element node with the "key= " attribute value I wanted. Would have saved much of the navigation code I had to write in the (TinyXML-based) XML plugin.
JDaniels13 is offline   Reply With Quote
Old 6th September 2006, 17:10   #43
mtyler
Junior Member
 
Join Date: Sep 2006
Location: San Diego
Posts: 4
I have integrated TinyXPath with this plugin

If anyone is interested, I have integrated the TinyXPath library with this plugin. It worked like a charm the very first time (surprised the heck out of me). Here are the steps:

1) Download TinyXPath from
http://tinyxpath.sourceforge.net/

2) Compile the TinyXPath LIB according to the instructions here http://tinyxpath.sourceforge.net/doc/index.html

3) Copy the tinyxpath.lib file along with all the TinyXPath .h (header files), excluding the TinyXML header files, to the XML Plugin source directory.

4) Add
code:
#include "xpath_static.h"
to the top of xml.cpp (XML Plugin source file)

5) Add the following code block to xml.cpp:

code:
extern "C" void __declspec(dllexport) _GotoXPath(HWND hwndParent, int string_size,
char *variables, stack_t **stacktop)
{
EXDLL_INIT();
{
popstring(szBuf);

nodeTmp = TinyXPath::XNp_xpath_node(node, szBuf);
if(nodeTmp)
{
node=nodeTmp;
pushstring("0");
return;
}
else
{
pushstring("-1");
}
}
}




6) Compile the XML Plugin source to the xml.dll file. Place the new xml.dll file in the NSIS/plugins directory (duh!)

7) Add the following code block to the XML.nsh file located in the NSIS/include directory:

code:

!define xml::GotoXPath `!insertmacro xml::GotoXPath`

!macro xml::GotoXPath _PATH _ERR
xml::_GotoXPath /NOUNLOAD `${_PATH}`
Pop ${_ERR}
!macroend



Viola! You're done. Use
code:
${xml::GotoXPath} "path" $errvar
in your installer script and the current node gets changed to the first node matching the XPath expression. If I have time, or someone else beats me to it, iterative expression matching could easily be added by storing the XPath state (by using the xpath_processor.h rather than xpath_static.h).

Ask if you need any help. Let me know if this helps. And thank you "Instructor" for the Xml Plugin (way better than the rest of them)
mtyler is offline   Reply With Quote
Old 6th September 2006, 17:48   #44
JDaniels13
Junior Member
 
Join Date: Aug 2006
Location: Olympia WA
Posts: 4
Thanks for your efforts! I'm not very handy with C++ builds; could you post the resulting XML.dll here?
JDaniels13 is offline   Reply With Quote
Old 6th September 2006, 18:29   #45
mtyler
Junior Member
 
Join Date: Sep 2006
Location: San Diego
Posts: 4
Here is the new xml.dll file

This site will not allow me to upload a DLL. I've zipped to see if it will accept it. You will need to modify xml.nsh according to my message.

Let me know if it works for you.
Attached Files
File Type: zip xml.zip (37.7 KB, 758 views)
mtyler is offline   Reply With Quote
Old 7th September 2006, 00:43   #46
mtyler
Junior Member
 
Join Date: Sep 2006
Location: San Diego
Posts: 4
Exclamation

PLEASE NOTE:

I hope that I have not overstepped my bounds by providing a modified version of xml.dll to this forum. The modification is based on the latest code base from "Instructor" and TinyXPath, but there are no promises of accuracy, reliability or safety, expressed or implied. Use at your own risk!

It would be nice if "Instructor" integrated this addition into the next build of his XML Plugin, giving it full XPath capabilities.
mtyler is offline   Reply With Quote
Old 8th September 2006, 07:55   #47
jeichhorn
Junior Member
 
Join Date: Jun 2005
Posts: 3
I am trying to use the ${xml::GotoXPath} command added by mtyler.

Here is my test.xml:

code:
<?xml version="1.0" encoding="utf-8" ?>
<test>
<c1>content1</c1>
<c2>
<c3>c3_content1</c3>
<c3>c3_content2</c3>
<c3>c3_content3</c3>
</c2>
</test>



I am trying to select the element /test/c2/c3 with the content 'c2_content2'.

When i use the xpath
code:
${xml::GotoXPath} "//c3[text()='c3_content2']" $0

the element is selected as expected, but when i use
code:
${xml::GotoXPath} "/test/c2/c3[text()='c3_content2']" $0

it does not find the element (result is -1).

Do i use the GotoXPath function in a wrong way in my second example?

Thanks for help.

Jörg
jeichhorn is offline   Reply With Quote
Old 8th September 2006, 17:01   #48
mtyler
Junior Member
 
Join Date: Sep 2006
Location: San Diego
Posts: 4
The immediate workaround for your problem is to execute
code:
${xml::RootElement} $1 $0
after loading the document and before conducting any static XPath queries that begin with the root element. Any XPath that is based on the top level element will work, including yours.

The way the TinyXML works is to have a node above the top level element for the document itself. From this node you can get the document name and access XML comments that are outside the scope of the top level element. The XML plugin maintains it state as the current or last node that was read. This enables you to jump around from a relative perspective. But, from a technical perspective, conducting a static XPath query from the document node will not work.

I considered modifying the GotoXPath function to account for this, but I think that it will defeat the purpose of the document node. So use the workaround specified above or use the XPath query Descendant notation along with the root element (even though this is not entirely accurate; you should use xml::RootElement):
code:
//test/c2/c3[text()='c3_content2']


The original GotoPath function looks for a leading slash in the path designation and moves the current node to the root element before it locates the desired element. This works well for this function because it is a simple navigation function. The TinyXPath library is a robust XPath processor that will not benefit from the same logic used by the GotoPath function. Therefore, the suggestions I made above should become the norm.

As usual, I hope that this has helped. Feel free to ask for assistance. I am appreciative of all the great tools and technologies supported by this community.
mtyler is offline   Reply With Quote
Old 10th September 2006, 13:48   #49
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Changed: Compiled statically without msvcrt.lib, now plugin work on Win95.
Added: Integrated TinyXPath v1.2.4 (thanks mtyler).
Added: ${xml::XPathString} -compute a string XPath expression.
Added: ${xml::XPathNode} -compute a node XPath expression and goes to it.
Added: ${xml::XPathAttribute} -compute an attribute XPath expression and goes to it.
Added: ${xml::CurrentAttribute} -returns name and value of the current attribute.
Updated: TinyXml to v2.5.1
Updated: StackFunc.h to v2.0


"XML" plugin v1.8

Download from Wiki
Instructor is offline   Reply With Quote
Old 24th November 2006, 10:50   #50
rtpHarry
Junior Member
 
Join Date: Nov 2006
Location: UK
Posts: 5
Send a message via ICQ to rtpHarry
possible bug in system

I almost abandoned this plugin yesterday when I was writing my installer. Now I have found a work around for it and I think its a great plugin again!

The problem arose when I tried to open an xml file for the second time. The first time I loaded the file (through a function attached to a custom page) it worked fine with this code (as I see it used in the forums as well):

PHP Code:
  ${xml::LoadFile"client-list.xml" $
The second time I used it was in a Section (for the install files part) and it failed with -1 every time until I saw somebody suggest for a different problem to prepend $EXEDIR to the start which fixed it.

PHP Code:
${xml::LoadFile"$EXEDIR\client-list.xml" $
rtpHarry is offline   Reply With Quote
Old 6th December 2006, 13:02   #51
atul123
Junior Member
 
Join Date: Dec 2006
Posts: 1
Where can I find examples of "How to use this XML plugin?"
atul123 is offline   Reply With Quote
Old 17th January 2007, 18:47   #52
niklasu
Junior Member
 
Join Date: Jan 2007
Location: Sweden
Posts: 1
XPathNode and XPathAttribute

Quote:
Originally posted by Instructor
Added: ${xml::XPathString} -compute a string XPath expression.
Added: ${xml::XPathNode} -compute a node XPath expression and goes to it.
Added: ${xml::XPathAttribute} -compute an attribute XPath expression and goes to it.
I'm trying to use XPathAttribute to change a setting in a web.config file, like this:
PHP Code:
${xml::LoadFile"$INSTDIR\Web.config" $0
${xml::XPathAttribute"/configuration/appSettings/add[@key='EPsConnection']" $0
${xml::SetAttribute"value" "some value" $0
${xml::SaveFile"$INSTDIR\Web.config" $0
${xml::Unload
But everytime the xml:XPathAttribute statement executes the installer crashes with the following message:
code:

Microsoft Visual C++ Runtime Library
Assertion failed!

Program: setup.exe
File: tinyxml.cpp
Line: 173

Expression: node->GetDocument() == 0 || node->GetDocument() == this->GetDocument()


(And I get the same error when using XPathNode too...)
What am I doing wrong here?
niklasu is offline   Reply With Quote
Old 18th January 2007, 20:38   #53
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
code:
${xml::LoadFile} "$INSTDIRWeb.config" $0
${xml::RootElement} $0 $1
${xml::XPathAttribute} "/configuration/appSettings/add[@key='EPsConnection']" $0
${xml::SetAttribute} "value" "some value" $0
${xml::SaveFile} "$INSTDIRWeb.config" $0
${xml::Unload}

Instructor is offline   Reply With Quote
Old 3rd February 2007, 12:10   #54
Yathosho
Forum King
 
Yathosho's Avatar
 
Join Date: Jan 2002
Location: AT-DE
Posts: 3,362
could you put this on the wiki please?
Yathosho is offline   Reply With Quote
Old 9th February 2007, 08:53   #55
Commerzpunk
Junior Member
 
Join Date: Feb 2007
Posts: 1
Thumbs up

Quote:
Originally posted by Instructor
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


I really tried hard to get this working for me.
The installer always crashed, when I tried to "InsertBeforeNode".

Now, I used this code and changed it, had several hundered crashes.

Here is the working result (for me):

code:

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

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

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

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

${xml::RootElement} $0 $1 # THATS THE SOLUTION FOR NO CRASHING!
MessageBox MB_OK "xml::RootElement$\n$$0=$0"
MessageBox MB_OK "xml::RootElement$\n$$1=$1"

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

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

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

${xml::Unload}



Messageboxes are for information and debugging only, of course!

Greets,

HA

Last edited by Commerzpunk; 9th February 2007 at 09:14.
Commerzpunk is offline   Reply With Quote
Old 10th May 2007, 19:31   #56
eafonsof
Junior Member
 
Join Date: May 2007
Posts: 1
Modify "value" attribute.

Hi there, I tried the following commands to modify the attribute named "value". It's not working as I expected. Does anybody know what's missing or wrong?
Thanks in advance.

;Format of config file:
;<?xml version="1.0" encoding="Windows-1252"?>
;<configuration>
; <appSettings>
; <add key="key1" value="value1" />
; <add key="key2" value="value2" />
; <add key="key3" value="value3" />
;
; <!-- Some comments -->
; <add key="key4" value="value4" />
; </appSettings>
;</configuration>

${xml::LoadFile} "$configFile" $0
${xml::RootElement} $0 $1
${xml::XPathAttribute} "/configuration/appSettings/add[@key='${KEY4}']" $0
${xml::SetAttribute} "value" "$newValue" $0
${xml::SaveFile} "$configFile" $0
${xml::Unload}

After this, the attribute "value" is set as an attribute of "<configuration" instead of the corresponding "<add" node.

i.e.
;
;<?xml version="1.0" encoding="Windows-1252"?>
;<configuration value="new_value4">
; <appSettings>
; <add key="key1" value="value1" />
; <add key="key2" value="value2" />
; <add key="key3" value="value3" />
;
; <!-- Some comments -->
; <add key="key4" value="value4" />
; </appSettings>
;</configuration>
eafonsof is offline   Reply With Quote
Old 18th May 2007, 19:40   #57
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
code:
${xml::LoadFile} "$configFile" $0
${xml::RootElement} $0 $1
${xml::XPathNode} "/configuration/appSettings/add[@key='${KEY4}']" $0
${xml::SetAttribute} "value" "$newValue" $0
${xml::SaveFile} "$configFile" $0
${xml::Unload}

Instructor is offline   Reply With Quote
Old 1st June 2007, 12:14   #58
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Updated: TinyXml to v2.5.3
Updated: TinyXPath to v1.3.0


"XML" plugin v1.9

Download from Wiki
Instructor is offline   Reply With Quote
Old 4th July 2007, 09:08   #59
DrDan
Member
 
Join Date: Apr 2007
Location: London, UK
Posts: 58
Question Question about the plugin

I'm working on an installer that uses this plug-in. Now, depending on the contents in my XML I need to run an external progam (in fact another NSIS uninstaller) that will read in the XML file and make changes to it.

The steps I am following are:

1) Open the XML file in the main installer
2) Manipulate as required
3) Determine if an external uninstaller is required
4) If an external uninstaller is required, then save the XML file, run the external uninstaller, re-load the XML file and carry on.
5) If no external uninstaller is required, carry on.

My question is, in step 4, should I also unload the XML plug-in (i.e. call ${xml::Unload}) before running the external uninstaller?

Thanks.
DrDan is offline   Reply With Quote
Old 10th July 2007, 05:20   #60
Wizarth
Junior Member
 
Join Date: Jul 2007
Posts: 2
SizeOf

Edit: Sorry, wrong thread.
Wizarth is offline   Reply With Quote
Old 20th August 2007, 09:46   #61
walb07
Junior Member
 
Join Date: Aug 2007
Posts: 2
Problem to parse XML with <!DOCTYPE ... []> element

Hi,

I've problems to parse an XML file which contains DTD description between xml header and first root element

Method ${xml::RootElement} returns with "-1". If I change the <!DOCTYPE ..[]> to a comment <!--DOCTYPE ...[]> which isn't really feasible it will work.

It would be helpful to support the DOCTYPE dtag by default.

example:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE RootElement [
<!ELEMENT RootElement (System+)>
<!ELEMENT System EMPTY>

<!ATTLIST RootElement Version CDATA #REQUIRED>
...
]>
<RootElement>
...
</RootElement>

with regards,
Dierk
walb07 is offline   Reply With Quote
Old 22nd January 2008, 10:09   #62
jogijhelumi
Junior Member
 
Join Date: Jan 2008
Posts: 3
I'm trying to use XPathNode for expressions with namespace i.e. fns: Deployment
, but it fails and return error code -1.

Is there any trick/workaround to use it in this way.
jogijhelumi is offline   Reply With Quote
Old 29th January 2008, 15:24   #63
FkYkko
Junior Member
 
Join Date: Jan 2008
Posts: 3
Hi I'm wondering if the attached plugin in this thread is the latest version of this plugin? It seems to me that the include file (xml.nsh) differs from the source code regarding some functions? For example, RemoveChild seems to return an error code while the include file and documentation does not specify any variable for this method. The RemoveAllChild function is not implemented in the source but is is availible in the documentation and include file?
Are there any updates regarding this? Maybe set up a simple sourceforge page to be able to update it?

or is there some other XML plugin which is generally used and better supported?

p.s. jogijhelumi: tinyxpath.sourceforge.net/ says that namespaces are not supported yet d.s.

Last edited by FkYkko; 29th January 2008 at 15:40.
FkYkko is offline   Reply With Quote
Old 30th January 2008, 14:31   #64
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
Updated: TinyXPath to v1.3.1

Fixed: missing "xml::_RemoveAllChild" in DLL.
Fixed: ${xml::RemoveNode} incorrectly documented.


"XML" plugin v2.0

Download from Wiki
Instructor is offline   Reply With Quote
Old 31st January 2008, 07:01   #65
FkYkko
Junior Member
 
Join Date: Jan 2008
Posts: 3
Thanks for the quick reply.
As it happens, I still have some problems with this plugin and have changed to nsisXML (by W) which works after some rewrites.
FkYkko is offline   Reply With Quote
Old 21st March 2008, 14:38   #66
Tzzz
Junior Member
 
Join Date: Mar 2008
Location: France
Posts: 1
XML::Xxxx functions: doc to improve

Hello,

It seems to have ben many misunderstanding since the new XML::Xxxx functions were launched:

Quote:
Added: ${xml::XPathString} -compute a string XPath expression.
Added: ${xml::XPathNode} -compute a node XPath expression and goes to it.
Added: ${xml::XPathAttribute} -compute an attribute XPath expression and goes to it.
I think that Instructor could get rid of most of them by improving the examples from its documentation:
In particular :
- Use of ${xml::RootElement} $0 $1 seems to fix many issues; please comment its use in XML::XPathNode, XML::XPathAttribute and XML::XPathString functions documentation whenever needed.
- Use of ${xml::XPathNode} "/configuration/components/component[@id='applicationSettings.default']/parameters/dbServerName" $0 is badly documented, i.e.:
. - XPath expression (e.g. "/a/b/@attr") is documented only for ${xml::XPathAttribute}, not for ${xml::XPathNode} whereas it seems to be afix for many cases.
. - Why is it that one shall use ${xml::XPathnode} prior to use a ${xml::SetAttribute} while logic would say to better use ${xml::XPathAttribute} instead. Instructor provides this kind of fixing but never fully explains why it is this way. Either fix ${xml::XPathAttribute} so that it allows to do what users think it should do, either fix the documentation so that its use is clearer compared to ${xml::XPathNode}.

Thank you very much for your plugin.
Tzzz is offline   Reply With Quote
Old 26th March 2008, 10:48   #67
xbarns
Senior Member
 
xbarns's Avatar
 
Join Date: Aug 2007
Location: Frankfurt, Germany
Posts: 187
Hi all,

i need to edit a xml structure like this

PHP Code:
<Configuration
<ConfigModule name="BlaBla">
 </
ConfigModule>
 <
ConfigModule name="FirebirdBridge" DefaultConfig="FALSE">
    <
Section name="FirebirdBridge" description="Configuration for Firebird DB Bridge">
      <
Data name="Host" type="string">127.0.0.1</Data>
      <
Data name="Database" type="string">C:\Program Files\Test\Database\Test.FDB</Data>
      <
Data name="User" type="string">User</Data>
      <
Data name="Password" type="string">Password</Data>
    </
Section>
  </
ConfigModule>
</
Configuration
In order to change the "<Data name="Database" type="string">C:\Program Files\Test\Database\Test.FDB</Data>" is there any other way then looping through the nodes and comparing attributes ?

i am already looping through the "ConfigModule" Nodes and comparing, is there an easier way?

Here is the code i have so far:

PHP Code:
${xml::LoadFile"$EXEDIR\scMaster.ctf" $0
loop
:
${
xml::FindNextElement"ConfigModule" $$1
${xml::ElementPath} $0
${xml::GetAttribute"name" $$

${IF} $== "FirebirdBridge"
        
    
${xml::GotoPath"$0/Section/Data" $1

    Loop here again 
?
         
         
${ELSE}
        Goto 
loop        
${ENDIF}

${
xml::FindCloseElement}
${
xml::SaveFile"$EXEDIR\scMaster2.ctf" $0
${xml::Unload

Thanks for helping
xbarns is offline   Reply With Quote
Old 26th April 2008, 13:05   #68
freeDB_man
Junior Member
 
Join Date: Jan 2008
Posts: 23
I tried to use this plug-in with the special build of NSIS that has a string length limitation of 8192 instead of 1024 but the plug-in is indifferent to the change and only reads 1024 chars.

Any workaround?
freeDB_man is offline   Reply With Quote
Old 11th June 2008, 07:46   #69
spitze
Junior Member
 
Join Date: May 2008
Location: Ingolstadt
Posts: 2
Hi all,
first of all great plugin. But i have a problem which i cannot solve.
I want to insert a line in an XML file.

The XML file looks like:


PHP Code:
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<adtf:configuration xmlns:adtv="adtv">
    <general_settings>
        <property name="gui_refresh_rate" value="25"/>
    </general_settings>
    <module_directories>
    </module_directories>
    <template_directories/>
</adtf:configuration>
Now i want to insert:

PHP Code:
        <directory path="C:\program files\Test"/> 
between

PHP Code:
<module_directories>
</
module_directories

I tried this piece of code

PHP Code:
${xml::FindNextElement"module_directories" $$1
${xml::CreateNode'<directory path="C:\program files\Test"/>' $4
${xml::InsertAfterNode} $$
The Output is:

PHP Code:
<module_directories />
<
directory path="C:\program files\Test"/> 
but it should be:

PHP Code:
<module_directories>
  <
directory path="C:\program files\Test"/>
</
module_directories
Any suggestions??
Thanx
spitze is offline   Reply With Quote
Old 11th June 2008, 09:28   #70
Instructor
Major Dude
 
Join Date: Jul 2004
Posts: 671
code:
${xml::FindNextElement} "module_directories" $0 $1
${xml::CreateNode} '<directory path="Crogram filesTest"/>' $4
${xml::InsertEndChild} $4 $5

Instructor is offline   Reply With Quote
Old 27th December 2008, 11:11   #71
radorl
Junior Member
 
Join Date: Dec 2008
Posts: 1
I'm editing XML file which uses &#DDDD; notation for non-ASCII characters. I noticed that after saving of modified XML file all &#DDDD; characters were replaced by original two-byte UTF-8 codes.

Is there some way how to instruct this wonderful plugin to use &#DDDD; notation?
radorl is offline   Reply With Quote
Old 20th March 2009, 06:36   #72
casioclave
Junior Member
 
Join Date: Mar 2009
Posts: 4
Question need some help

Hi. Can U help me to change value in this stiring <value>en</value> from "en" to "ru"

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="inVisit.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
<clear />
<add name="LocalSqlServer" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
<add name="inVisit.Properties.Settings.ivConnection" connectionString="Data Source=.\sqlexpress;AttachDbFilename=;Initial Catalog=ivData;Integrated Security=True;Connect Timeout=30"
providerName="" />
</connectionStrings>
<userSettings>
<inVisit.Properties.Settings>
<setting name="WinFormState" serializeAs="String">
<value>Normal</value>
</setting>
<setting name="WinFormSize" serializeAs="String">
<value>800, 600</value>
</setting>
...
<setting name="Language" serializeAs="String">
<value>en</value>
</setting>
<setting name="AutoCheckOut" serializeAs="String">
<value>False</value>
</setting>

</userSettings>
</configuration>

Last edited by casioclave; 20th March 2009 at 09:36.
casioclave is offline   Reply With Quote
Old 26th May 2009, 14:03   #73
mattm591
Guest
 
Posts: n/a
I am trying to use this plugin to get values from an XML structure.

The document looks something like this:

<xml>
<groups>
<group id="1">
<name>Group 1</name>
</group>
<group id="2">
<name>Group 2</name>
</group>
<group id="3">
<name>Group 3</name>
</group>
</groups>
</xml>

I want to get the values of id and name and am currently working on getting value. After loading the document I can get the value of the first group (id 1) by doing this,
PHP Code:
${xml::GotoPath"/xml/groups/group" $0
${xml::GetAttribute"id" $$
but I cannot get any others.

The code I am trying uses {xml::NextAttribute} and no matter what I do I alway get -1 returned for $2 and $0 and $1 are null. I originally tried it like this to get the loop, but it doesn't work even if I only run it once.
PHP Code:
${xml::NextAttribute} $$$2
${While} $!= -1
  
${xml::NextAttribute} $$$2
  MessageBox MB_OK 
$0
${EndWhile} 
Can anyone please tell me what I'm doing wrong and how I can access these values.
  Reply With Quote
Old 27th May 2009, 14:37   #74
mattm591
Guest
 
Posts: n/a
Ok I have managed to get it working.

For anyone else with a similar issue here is what I did. (I used LastChild and PreviousSibling because I wanted to get the xml in reverse, replace with FirstChild and NextSibling to go through in order). Also, I make use of LogicLib which you will need to include if you're copying this example.

PHP Code:
${xml::GotoPath"/xml/groups" $0
${xml::LastChild"group" $$0

${While} $== 0

  
#get the group id
  
${xml::GetAttribute"id" $$3

  
#get the group name
  
${xml::FirstChildElement"name" $$4
  
${xml::GetText} $$3

  
#move to next group
  
${xml::Parent} $$4
  
${xml::PreviousSibling"group" $$0

${EndWhile} 
  Reply With Quote
Old 18th October 2009, 22:26   #75
sag47
Member
 
Join Date: Dec 2006
Posts: 50
Send a message via AIM to sag47
Here is a nice small example of using this plugin. In my installer header I included XML.nsh.

code:
include "XML.nsh"


Here is a sample XML file that you should extract to the temp folder ($TEMP).

code:
<?xml version='1.0' encoding='UTF-8' ?>

<account version='1.0'>
<account>
<protocol>prpl-jabber</protocol>
<name></name>
<settings>
<setting name='use-global-buddyicon' type='bool'>1</setting>
<setting name='require_tls' type='bool'>1</setting>
<setting name='ft_proxies' type='string'>gtalk.google.com:7777</setting>
<setting name='check-mail' type='bool'>0</setting>
<setting name='connect_server' type='string'>gtalk.google.com</setting>
<setting name='old_ssl' type='bool'>0</setting>
<setting name='auth_plain_in_clear' type='bool'>0</setting>
<setting name='buddy_icon_timestamp' type='int'>0</setting>
<setting name='port' type='int'>443</setting>
<setting name='custom_smileys' type='bool'>1</setting>
</settings>
<settings ui='gtk-gaim'>
<setting name='auto-login' type='bool'>1</setting>
</settings>
</account>
</account>



Basically what I wanted to do in the XML file above was to set text inside of the <name></name> XML node to text that is dependent on user options in my installer. Here's my NSIS code that I use to modify the above XML:
PHP Code:
  ${xml::LoadFile"$TEMP\\accounts.xml" $0
  IntCmp 
$0 0 +++2
  MessageBox MB_OK
|MB_ICONSTOP "Error loading accounts.xml!"
  
${xml::RootElement} $$0
  
${xml::FirstChildElement"" $$0
  
${xml::FirstChildElement"name" $$0
  DetailPrint 
"Setting [email]sam@gtalk.google.com[/email]/Home"
  
${xml::SetText"sam@gtalk.google.com/Home" $0
  IntCmp 
$0 0 +++2
  MessageBox MB_OK
|MB_ICONSTOP "Error setting username!"
  
${xml::SaveFile"" $0
  IntCmp 
$0 0 +++2
  MessageBox MB_OK
|MB_ICONSTOP "Error saving accounts.xml!"
  
${xml::Unload
Commands above explained...[list=1][*]${xml::LoadFile} "$TEMP\accounts.xml" $0 loads my XML file to be modified.[*]${xml::RootElement} $1 $0 selects the root node <account version='1.0'>[*]${xml::FirstChildElement} "" $1 $0 selects the first childnode located in the root node (which happens to be <account>). No argument means select the first childnode no matter what its name is.[*]${xml::FirstChildElement} "name" $1 $0 selects the first childnode within the node accounts > accounts that has the name "name" or <name></name>.[*]${xml::SetText} "sam@gtalk.google.com/Home" $0 sets the text inside of <name></name> so the result is <name>sam@gtalk.google.com/Home</name>[*]${xml::SaveFile} "" $0 saves changes that I've made to my XML file. No argument means save to the same file that was originally opened[*]${xml::Unload} unloads the XML plugin since I'm done modifying my XML file.[*]If you're wondering about IntCmp $0 0 +2 +1 +2, $0 is the error code returned by the given XML command. IntCmp compares the integer variable $0 with the integer 0 (zero). If $0 is equal to 0 then go down +2 commands (skipping the error message). If $0 is less than 0 then go down +1 command (show the error message). If $0 is greater than 0 then go down +2 commands (skip the error message). Skipping commands like that ignores comments.[/list=1]

Here is what my XML file looks like after being modified...
code:
<?xml version='1.0' encoding='UTF-8' ?>

<account version='1.0'>
<account>
<protocol>prpl-jabber</protocol>
<name>sam@gtalk.google.com/Home</name>
<settings>
<setting name='use-global-buddyicon' type='bool'>1</setting>
<setting name='require_tls' type='bool'>1</setting>
<setting name='ft_proxies' type='string'>gtalk.google.com:7777</setting>
<setting name='check-mail' type='bool'>0</setting>
<setting name='connect_server' type='string'>gtalk.google.com</setting>
<setting name='old_ssl' type='bool'>0</setting>
<setting name='auth_plain_in_clear' type='bool'>0</setting>
<setting name='buddy_icon_timestamp' type='int'>0</setting>
<setting name='port' type='int'>443</setting>
<setting name='custom_smileys' type='bool'>1</setting>
</settings>
<settings ui='gtk-gaim'>
<setting name='auto-login' type='bool'>1</setting>
</settings>
</account>
</account>



Note: I changed XML values from my actual installer for the sake of this quick example to help get others started. So I would ignore the actual content because it has no use at all.

It took only a couple of minutes of reading the documentation that came with the XML plugin for NSIS that I created the above functions. So read the documentation for a better explanation of all of the capabilities possible with this wonderful plugin.

Sam Gleske

Last edited by sag47; 18th October 2009 at 22:52.
sag47 is offline   Reply With Quote
Old 9th November 2009, 09:31   #76
ChocJunkie
Senior Member
 
Join Date: Oct 2009
Location: Germany
Posts: 120
What's the difference between using
code:
${FirstChildElement} "name" $var1 $var2
and
code:
${FirstChild} "name" $var1 $var2
for getting a element child? Especially, I'm interested what ${FirstChildElement} exists for, if the task can be done using ${FistChild}. A child can only be of type text or element. So that ${FirstChild} "Name" does search for a element child, doesn't it?

Thanks

CJ
ChocJunkie is offline   Reply With Quote
Old 25th November 2009, 09:46   #77
ChocJunkie
Senior Member
 
Join Date: Oct 2009
Location: Germany
Posts: 120
It think the plugin is missing a flug that declares the XML.nsh as already included!?

CJ
ChocJunkie is offline   Reply With Quote
Old 18th December 2009, 15:25   #78
phungus420
Junior Member
 
Join Date: Apr 2009
Posts: 15
I'm not a programmer by trade and cannot figure out how to do what I need to do. As background I have an installer for a video game mod, however it only works if the user has patched the game, and it's a frequent issue where users don't patch and then complain that the mod causes a crash. I wanted to have the installer abort if the game isn't patched, and used a registry check, which works fine for 90% of users. Unfortunately a certain distributer (STEAM) does not sign a version key to their registry, so I can't check the version number using the registry for steam users. Also the script is a bit overly complex with all the various registry checks it needs to do anyway.

There is a simpler way, the game has an XML document that contains the version number. I tried to use the text reading function by Stu, but it fails, I assume because it's an XML file and not a text document. So looking around I found this plug in. Common sense would show that this plug in can be used to do what I want, unfortunately I can not figure out how to use it.

Basically I want to open up an XML file, I know how to get NSIS to find the file on the user's computer. Then I want to open it, go to line 10, and read what's there and return true if it's version is 319 and false if not. The specific XML tag is this:
code:
<Define>
<DefineName>CIV4_VERSION</DefineName>
<iDefineIntVal>319</iDefineIntVal>
</Define>


The iDefineIntVal is on line 10, and will always be on line 10. This is why this method would be superior to the registry check I'm currently using (which fails for some users).

Does anyone know how to read this, and get a true/false (or 1/0 etc) response if it's what it should be?
phungus420 is offline   Reply With Quote
Old 18th December 2009, 18:11   #79
msroboto
Junior Member
 
Join Date: Sep 2006
Posts: 47
nsisXML::select /NOUNLOAD '/Define/iDefineIntVal'
${If} $1 != "0"
nsisXML::getText /NOUNLOAD
;the result should be in $3
${If} $3 == "319"
;do what you want
${Endif}
${Endif}
msroboto is offline   Reply With Quote
Old 18th December 2009, 18:48   #80
phungus420
Junior Member
 
Join Date: Apr 2009
Posts: 15
Quote:
Originally posted by msroboto
nsisXML::select /NOUNLOAD '/Define/iDefineIntVal'
${If} $1 != "0"
nsisXML::getText /NOUNLOAD
;the result should be in $3
${If} $3 == "319"
;do what you want
${Endif}
${Endif}
Thanks for the response and help. But I can't figure this out. Where am I defining the file I am loading from? Also the whole document is iDefineIntVal tags like the above, I need it to read specifically the one on line 10, or the one that the XML is defining as CIV4_VERSION. As an example here is a snippet of the XML file:

code:
<Define>
<DefineName>CIV4_VERSION</DefineName>
<iDefineIntVal>319</iDefineIntVal>
</Define>
<Define>
<DefineName>MIN_VERSION</DefineName>
<iDefineIntVal>000</iDefineIntVal>
</Define>
<Define>
<DefineName>SAVE_VERSION</DefineName>
<iDefineIntVal>302</iDefineIntVal>
</Define>
...


Obviously I just want the CIV4_VERSION tag. So how do I:
1)define the XML file I'm reading this from (this file is on the User's computer, and I set the path off of the install directory; I can run a check for if the file exists easily, so defining it is easy, I just don't understand how to pass that to the XML NSIS function here)
2)Define which tag to read
phungus420 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