Jump to content

Recommended Posts

Posted (edited)
  On 9/28/2019 at 1:10 AM, Hiyoal said:

Different length than yours but the object is of the same type??

Expand  

That means that we are not using the same xml file.  Which leads me to believe that there may be even more differences.  Did you make any changes to any of the files after you unzipped it?

 

*** Update ***

I just downloaded the latest version again and I get a length of 13 also.

Edited by TheXman
Posted (edited)

@Hiyoal

Okay, I think I found the issue.  The difference is my xml.au3.  It appears that I had found an issue with it a while ago and fixed it in my version.  The issue actually was related to Example 6. 

Please try the xml.au3 file that I have attached.  Please let me know if it resolves the issue you are having.  You can do a diff between mine and the one in the latest zip if you want to see the modifications.  There are only 2 changes.  One line was modified and the other line was added.

 

@mLipok

If you need an explanation of my modifications, please let me know.  I would be happy to explain the issue that I found and how the 2 lines fix the issue with Example 6.

 

 

XML.au3Fetching info...

Edited by TheXman
Posted

Champion. 

Thats working now for the example and my own script.

I saw the changes. The addition to validate the object made sense but I didn't understand the removal of the "#text" ContinueLoop in that for loop.

Im stoked I wasn't going bonkers, thanks for the help TheXman.

Posted

 

You're welcome!   :thumbsup:

 

  On 9/28/2019 at 2:40 AM, Hiyoal said:

I didn't understand the removal of the "#text" ContinueLoop in that for loop.

Expand  

It has to do with the  data in the _ArrayDisplay().  If you comment out that line, you will see #text entries in the table and you will see several COM errors saying something about trying to assign null objects.  So basically that line just omits any #text properties from being added to the table, which also prevents the COM errors.

Posted

Haha makes sense.

As soon as I wrote my post I started tinkering away with checking nodeNames individually without going through _XML_Array_GetNodesProperties and saw all of those #text entries.

  • 6 months later...
Posted (edited)
  On 9/28/2019 at 2:49 AM, TheXman said:

 

You're welcome!   :thumbsup:

 

It has to do with the  data in the _ArrayDisplay().  If you comment out that line, you will see #text entries in the table and you will see several COM errors saying something about trying to assign null objects.  So basically that line just omits any #text properties from being added to the table, which also prevents the COM errors.

Expand  

Hi TheXman,

I'm having a strange issue while using "_XML_CreateDOMDocument","_XML_Load" "_XML_SaveToFile" .

While opening Windows SIM "unattend.xml" files using your "XML.au3" UDF (By the way great work by picking up "eltorro" code and adding extra features)

I'm having some issues:

Using "_XML_CreateDOMDocument" and setting up as "Default" (in my case it ends up being "6") I get the following output (upon Load and SaveToFile😞

 

<?xml version="1.0" encoding="utf-8"?><unattend xmlns="urn:schemas-microsoft-com:unattend">

 

Thus missing a "CRLF" at the first entry.

 

I have to change the parameter to "3" to get the proper result (equal to the original file):


Like this:

<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">

 

I Just wanted to know if this is normal and related to "__XML_MiscProperty_DomVersion" function, or not.

Because I can keep the "3" to produce the same result. And in fact this is only a glitch (they are both valid to the best of my knowledge) .

 

Nonetheless I do have another more serious issue. Apparently Microsoft is creating special XML's when using WSIM for "SynchronousCommand wcm:action" :

For their own parsing code they require the both " and ' to be represented by &quot; and &apos;  , just to differentiate from their own XML code. 

                <SynchronousCommand wcm:action="add">
                    <Order>1</Order>
                    <Description>Never Expires</Description>
                    <CommandLine>cmd /C WMIC USERACCOUNT WHERE &quot;Name=&apos;TESTUSER&apos;&quot; SET PasswordExpires=FALSE</CommandLine>
                    <RequiresUserInput>false</RequiresUserInput>
                </SynchronousCommand>

 

Unfortunately while using the functions  "_XML_Load" and then "_XML_SaveToFile" all data containing ([&quot;] and [&apos;]) get back to (" and '), resulting in:

 

                <SynchronousCommand wcm:action="add">
                    <Order>1</Order>
                    <Description>Never Expires</Description>
                    <CommandLine>cmd /C WMIC USERACCOUNT WHERE "Name='TESTUSER'" SET PasswordExpires=FALSE</CommandLine>
                    <RequiresUserInput>false</RequiresUserInput>
                </SynchronousCommand>

 

I know this is "kind" of normal, but is there any way to avoid this? I mean keeping the original Raw data? 

 

Thanks in advance,

Regards.

 

 

 

Edited by fjorger
Posted
  On 3/28/2020 at 10:06 PM, fjorger said:

Hi TheXman,

. . .

While opening Windows SIM "unattend.xml" files using your "XML.au3" UDF (By the way great work by picking up "eltorro" code and adding extra features)

Expand  

As you can see in the 1st post of this topic, this is @mLipok's UDF.  I am just an experienced user of it.  :)

Posted
  On 3/29/2020 at 2:34 AM, TheXman said:

As you can see in the 1st post of this topic, this is @mLipok's UDF.  I am just an experienced user of it.  :)

Expand  

Hi TheXman,

Thanks for pointing that out (very silly mistake)😞

@mLipok: My sincere apologies 🤕 (and thanks for your valued work👍).

About the  " and ' to be represented by &quot; and &apos;  while using WSIM, well I discovered that works regardless ;) (using both formats), so no problem whatsoever.

So now I'm just curious about the missing ( "CRLF" at the first entry.) when using "6" instead of "3", could this be a "glitch" in the parsing code, or work as intended?

Best Regards,

FJorgeR.

 

Posted (edited)

Can you attach the shortest script and xml file that reproduces the issue?

Update:

@fjorger

You can disregard the request for a script and test file.  I was able to recreate the issue on my workstation.  When preserving white space, I'm clueless as to why there's a difference between msxml3.dll and msxml6.dll, but there is.  :think:  As you've pointed out, the old version seems to work correctly,

Although this is purely speculation on my part, when releasing msxml6.dll, maybe there was a decision to only preserve white space starting from the XML's root element, not any white space that may occur between the XML prolog and the root element.  No matter how much white space is between the XML prolog and the root xml element, when preserve white space property is true, it is all stripped when using msxml6.dll.

Even this:

<?xml version="1.0" encoding="UTF-8"?>



<SETTINGS>


</SETTINGS>

Becomes this, when using msxml6, with the PreserveWhiteSpace property set to true:

<?xml version="1.0" encoding="UTF-8"?><SETTINGS>


</SETTINGS>

 

Edited by TheXman
Posted (edited)

@fjorger

If you want to ensure that the XML prolog is on its own line (regardless of the MSXML version), then you can TIDY the XML and write the file using a non-XML write function:

#include <xml.au3>

example()

Func example()
    Const $XML_DATA  = _
                       '<?xml version="1.0" encoding="UTF-8"?>' & @CRLF & _
                       @CRLF & _
                       @CRLF & _
                       @CRLF & _
                       '<SETTINGS>' & @CRLF & _
                       @CRLF & _
                       @CRLF & _
                       '</SETTINGS>'

    Local $oXmlDoc
    Local $sXML

    $oXmlDoc = _XML_CreateDOMDocument()     ;Create xml object
    _XML_LoadXML($oXmlDoc, $XML_DATA)       ;Load XML
    $sXML = _XML_Tidy($oXmlDoc, "UTF-8")    ;Tidy XML
    ConsoleWrite($sXML & @CRLF)             ;Display XML
    FileWrite("test.xml", $sXML)            ;Write XML
EndFunc

Output & content of test.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SETTINGS>


</SETTINGS>

 

Edited by TheXman
Posted
  On 3/29/2020 at 3:24 AM, TheXman said:

Can you attach the shortest script and xml file that reproduces the issue?

Update:

@fjorger

You can disregard the request for a script and test file.  I was able to recreate the issue on my workstation.  When preserving white space, I'm clueless as to why there's a difference between msxml3.dll and msxml6.dll, but there is.  :think:  As you've pointed out, the old version seems to work correctly,

Although this is purely speculation on my part, when releasing msxml6.dll, maybe there was a decision to only preserve white space starting from the XML's root element, not any white space that may occur between the XML prolog and the root element.  No matter how much white space is between the XML prolog and the root xml element, when preserve white space property is true, it is all stripped when using msxml6.dll.

Even this:

<?xml version="1.0" encoding="UTF-8"?>



<SETTINGS>


</SETTINGS>

Becomes this, when using msxml6, with the PreserveWhiteSpace property set to true:

<?xml version="1.0" encoding="UTF-8"?><SETTINGS>


</SETTINGS>

 

Expand  

Hi TheXman,

Apologies for the late reply. 

Thanks for the investigation,  you nailed it.

The mystery is now solved ;)

Posted
  On 3/29/2020 at 6:59 PM, fjorger said:

Thanks for the investigation,  you nailed it.

The mystery is now solved 

Expand  

You're welcome!  Glad I could help.  :thumbsup:

Posted
  On 3/29/2020 at 2:07 PM, TheXman said:

@fjorger

If you want to ensure that the XML prolog is on its own line (regardless of the MSXML version), then you can TIDY the XML and write the file using a non-XML write function:

#include <xml.au3>

example()

Func example()
    Const $XML_DATA  = _
                       '<?xml version="1.0" encoding="UTF-8"?>' & @CRLF & _
                       @CRLF & _
                       @CRLF & _
                       @CRLF & _
                       '<SETTINGS>' & @CRLF & _
                       @CRLF & _
                       @CRLF & _
                       '</SETTINGS>'

    Local $oXmlDoc
    Local $sXML

    $oXmlDoc = _XML_CreateDOMDocument()     ;Create xml object
    _XML_LoadXML($oXmlDoc, $XML_DATA)       ;Load XML
    $sXML = _XML_Tidy($oXmlDoc, "UTF-8")    ;Tidy XML
    ConsoleWrite($sXML & @CRLF)             ;Display XML
    FileWrite("test.xml", $sXML)            ;Write XML
EndFunc

Output & content of test.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SETTINGS>


</SETTINGS>

 

Expand  

Hi again, 

Thank you very much for the function example,  but because I'm loading data from an existing xml file (_XML_Load) then I'm just changing some data (ComputerName) and dumping the data to the same file.

So I would only need the following (first line only): 

Func example()     Const $XML_DATA  = _                        '<?xml version="1.0" encoding="UTF-8"?>' & @CRLF

 

Then I would had to strip the existing (first line). But no worries, I will just force (version 3).

Thanks again for your time and help (appreciated) 

 

  • 3 months later...
Posted (edited)

The function _XML_UpdateField does not work, if an element has no text (I'm using the latest version 1.1.1.13 of the UDF).

This code works:

#include "XML.au3"

Local $sXml = _
    "<root>" & _
        "<child>sometext</child>" & _
    "</root>"

Local $oXmlDoc = _XML_CreateDOMDocument()
_XML_LoadXML($oXmlDoc, $sXml)
_XML_UpdateField($oXmlDoc, "//child", "test")
If @error Then ConsoleWrite("_XML_UpdateField: @error = " & @error & @CRLF)

But when following code is used (only the text of the element "child" has been removed) the function _XML_UpdateField results in @error = 1:

#include "XML.au3"

Local $sXml = _
    "<root>" & _
        "<child></child>" & _
    "</root>"

Local $oXmlDoc = _XML_CreateDOMDocument()
_XML_LoadXML($oXmlDoc, $sXml)
_XML_UpdateField($oXmlDoc, "//child", "test")
If @error Then ConsoleWrite("_XML_UpdateField: @error = " & @error & @CRLF)

 

Edited by DonChunior
Added version information.
Posted (edited)

  

  On 7/22/2020 at 1:34 PM, DonChunior said:

The function _XML_UpdateField does not work, if an element has no text

Expand  

I'm not sure if it was written that way for a reason or whether it is just a small oversight.  However, it only takes a small modification to make it work even if the specified element does not have a text node. 

If you replace the existing function with the one below, it should work either with or without an existing text node.  I tried to make the smallest modification possible in order for it to work.  Keep in mind that this is not my UDF and I do not maintain it.  Therefore, the modified function may or may not get included in any future version.

Func _XML_UpdateField(ByRef $oXmlDoc, $sXPath, $sData) ; Modified by TheXman to create a text node if one does not already exist
    ; Error handler, automatic cleanup at end of function
    Local $oXML_COM_ErrorHandler = ObjEvent("AutoIt.Error", __XML_ComErrorHandler_InternalFunction)
    #forceref $oXML_COM_ErrorHandler

    Local $bUpdateStatus  = False
    Local $oNode_Selected = _XML_SelectSingleNode($oXmlDoc, $sXPath)
    If @error Then
        Return SetError(@error, @extended, $XML_RET_FAILURE)
    ElseIf $oNode_Selected.hasChildNodes Then
        For $oNode_enum_Child In $oNode_Selected.childNodes()
            If $oNode_enum_Child.nodetype = $XML_NODE_TEXT Then
                $oNode_enum_Child.Text = $sData
                $bUpdateStatus = True
                ExitLoop
            EndIf
        Next
    EndIf

    If Not $bUpdateStatus Then
        Local $oNode_Created = $oXmlDoc.createTextNode($sData)
        $oNode_Selected.appendChild($oNode_Created)
        If @error Then Return SetError($XML_ERR_NODEAPPEND, @error, $XML_RET_FAILURE)
    EndIf

    Return SetError($XML_ERR_SUCCESS, $XML_EXT_DEFAULT, $XML_RET_SUCCESS)
EndFunc   ;==>_XML_UpdateField

 

Edited by TheXman
Posted (edited)
  On 7/23/2020 at 5:49 PM, TheXman said:

I'm not sure if it was written that way for a reason or whether it is just a small oversight.  However, it only takes a small modification to make it work even if the specified element does not have a text node.

Expand  

I think it's a bug in the UDF.
If it were not, then the following code should also result in a error, but it does not:

#include "XML.au3"

Local $sXml = _
    "<root>" & _
        "<child>sometext</child>" & _
    "</root>"

Local $oXmlDoc = _XML_CreateDOMDocument()
_XML_LoadXML($oXmlDoc, $sXml)
_XML_UpdateField($oXmlDoc, "//child", "")
If @error Then ConsoleWrite("_XML_UpdateField: @error = " & @error & @CRLF)
_XML_UpdateField($oXmlDoc, "//child", "test")
If @error Then ConsoleWrite("_XML_UpdateField: @error = " & @error & @CRLF)

Since the last, most current version of the UDF is from March 2017, I don't have much hope that there will be a bugfix.

Nevertheless, thank you very much for your efforts!
I will try out the function you customized!

Edited by DonChunior
  • 1 month later...
Posted
  On 9/24/2020 at 10:11 AM, DonChunior said:

 ill you look at ....

Expand  

here you are, waiting for your results

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

  Reveal hidden contents

Signature last update: 2023-04-24

  • 2 weeks later...
Posted (edited)
  On 9/24/2020 at 10:11 AM, DonChunior said:

@mLipok, will you look at the problem I reported on 22-Jul-2020 and correct it in the UDF?

Expand  

@mLipok, see if you think this is an acceptable solution to @DonChunior's problem:

; #FUNCTION# ====================================================================================================================
; Name ..........: _XML_UpdateField
; Description ...: Update existing single node based on XPath specs.
; Syntax ........: _XML_UpdateField(ByRef $oXmlDoc, $sXPath, $sData)
; Parameters ....: $oXmlDoc   - [in/out] an object. A valid DOMDocument or IXMLDOMElement object
;                  $sXPath    - a string value. The XML tree path from root node (root/child/child..)
;                  $sData     - The data to update the node with.
; Return values .: On Success - Returns $XML_RET_SUCCESS
;                  On Failure - Returns $XML_RET_FAILURE and sets the @error flag to non-zero (look in #Region XML.au3 - ERROR Enums)
; Author ........: Eltorro
; Modified ......: Weaponx, mLipok, GMK
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; [yes/no]
; ===============================================================================================================================
Func _XML_UpdateField(ByRef $oXmlDoc, $sXPath, $sData)
    ; Error handler, automatic cleanup at end of function
    Local $oXML_COM_ErrorHandler = ObjEvent("AutoIt.Error", __XML_ComErrorHandler_InternalFunction)
    #forceref $oXML_COM_ErrorHandler

    Local $oNode_Selected = _XML_SelectSingleNode($oXmlDoc, $sXPath)
    If @error Then Return SetError(@error, @extended, $XML_RET_FAILURE)
    If Not $oNode_Selected.hasChildNodes And $oNode_Selected.nodetype <> $XML_NODE_ELEMENT And $oNode_Selected.nodetype <> $XML_NODE_TEXT Then _
            Return SetError($XML_ERR_INVALIDNODETYPE, $XML_EXT_DEFAULT, $XML_RET_FAILURE)

    If $oNode_Selected.hasChildNodes Then
        Local $bUpdateStatus = False
        For $oNode_enum_Child In $oNode_Selected.childNodes()
            If $oNode_enum_Child.nodetype = $XML_NODE_ELEMENT OR $oNode_enum_Child.nodetype = $XML_NODE_TEXT Then
                $oNode_enum_Child.Text = $sData
                $bUpdateStatus = True
                ExitLoop
            EndIf
        Next

        If Not $bUpdateStatus Then
            Local $oNode_Created = $oXmlDoc.createTextNode($sData)
            $oNode_Selected.appendChild($oNode_Created)
            If @error Then Return SetError($XML_ERR_NODEAPPEND, @error, $XML_RET_FAILURE)
        EndIf

    ElseIf $oNode_Selected.nodetype = $XML_NODE_ELEMENT OR $oNode_Selected.nodetype = $XML_NODE_TEXT Then
        $oNode_Selected.Text = $sData
    EndIf

    Return SetError($XML_ERR_OK, $XML_EXT_DEFAULT, $XML_RET_SUCCESS)
EndFunc   ;==>_XML_UpdateField

 

Edited by GMK
Error $XML_ERR_INVALIDNODETYPE

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...