WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: mlburgoon71 on May 21, 2023, 07:54:18 PM

Title: Read data from an XML file.
Post by: mlburgoon71 on May 21, 2023, 07:54:18 PM
I am trying to write a program to help me with modding some games I play.  I am struggling with figuring out the best way to read in values from the default .xml file, provided by the game, so I can change and manipulate them.  small snippet Example below of the xml file.

But what I want to be able to do is pull the value like so..

eg =  (some command) (/entity_classes/entity_class(@name="zombieNurseFeral")/property(@name="ExperienceGain")

how is this possible to do??  been looking at the wbOmnibus extender and it sounded promising.  but having issues getting it to work. I am hoping I don't have to create my own parser to do this.....

excerpt from the game .xml.
<entity_classes>
<entity_class name="zombieNurse" extends="zombieTemplateMale">
   <property name="Tags" value="entity,zombie,walker"/>
   <property name="Mesh" value="#Entities/Zombies?Prefabs/ZNurse.prefab"/>
   <property name="SoundRandom" value="Enemies/Base_Zombie_Female/zombiefemaleroam"/>
   <property name="SoundAlert" value="Enemies/Base_Zombie_Female/zombiefemalealert"/>
   <property name="SoundAttack" value="Enemies/Base_Zombie_Female/zombiefemaleattack"/>
   <property name="SoundHurt" value="Enemies/Base_Zombie_Female/zombiefemalepain"/>
   <property name="SoundDeath" value="Enemies/Base_Zombie_Female/zombiefemaledeath"/>
   <property name="SoundSense" value="Enemies/Base_Zombie_Female/zombiefemalesense"/>
   <property name="AvatarController" value="AvatarZombie01Controller"/>
   <property name="ModelType" value="Standard"/>
   <property name="WalkType" value="7"/>
   <property name="Mass" value="130"/>
   <property name="RootMotion" value="true"/>
   <property name="HasDeathAnim" value="true"/>
   <property name="AIPathCostScale" value=".5, .65"/>
   <property name="DanceType" value="2" />

   <!-- Gameplay zombieNurse -->
   <property name="MoveSpeedAggro" value="0.3, 1.35"/> <!-- slim, regular -->
   <property name="HandItem" value="meleeHandZombie01"/>
   <effect_group name="Base Effects">
      <passive_effect name="HealthMax" operation="base_set" value="125"/>
   </effect_group>
</entity_class>

<entity_class name="zombieNurseFeral" extends="zombieNurse">
   <property name="Tags" value="entity,zombie,walker,feral"/>
   <property name="Mesh" value="#Entities/Zombies?Prefabs/ZNurseFeral.prefab"/>

   <!-- Gameplay zombieNurseFeral -->
   <property name="DismemberMultiplierHead" value=".7"/><property name="DismemberMultiplierArms" value=".7"/><property name="DismemberMultiplierLegs" value=".7"/><!-- Feral -->
   <property name="PainResistPerHit" value=".7"/><!-- Feral -->
   <property name="MoveSpeedAggro" value="0.6, 1.45"/> <!-- slim, feral -->
   <property name="JumpMaxDistance" value="4.6, 5"/>
   <property name="HandItem" value="meleeHandZombieFeral"/>
   <property name="ExperienceGain" value="750"/><!-- XP grunt feral -->
   <property name="LootDropProb" value=".03"/> <!-- Feral -->

   <effect_group name="Base Effects">
      <passive_effect name="HealthMax" operation="base_set" value="237"/>
      <!--<passive_effect name="EntityDamage" operation="perc_add" value="0"/>--> <!-- Feral damage -->
   </effect_group>
</entity_class>

<entity_class name="zombieNurseRadiated" extends="zombieNurseFeral">
   <property name="Tags" value="entity,zombie,walker,feral,radiated"/>
   <property name="Mesh" value="#Entities/Zombies?Prefabs/ZNurseRadiated.prefab"/>

   <!-- Gameplay zombieNurseRadiated -->
   <property name="DismemberMultiplierHead" value=".4"/><property name="DismemberMultiplierArms" value=".4"/><property name="DismemberMultiplierLegs" value=".4"/><!-- Radiated -->
   <property name="PainResistPerHit" value=".9"/><!-- Radiated -->
   <property name="ExperienceGain" value="1200"/><!-- XP grunt radiated -->

   <effect_group name="Base Effects">
      <passive_effect name="HealthMax" operation="base_set" value="451"/>
      <!--<passive_effect name="EntityDamage" operation="perc_add" value="0"/>--><!-- Feral damage -->
      <triggered_effect trigger="onOtherDamagedSelf" action="ModifyCVar" target="self" cvar="RadiatedRegenAmount" operation="set" value="4"/>
      <triggered_effect trigger="onOtherDamagedSelf" action="AddBuff" target="self" buff="buffRadiatedRegen"/>
   </effect_group>
</entity_class>
</entity_classes>
Title: Re: Read data from an XML file.
Post by: stanl on May 22, 2023, 04:19:13 AM
I'm sure Jim would like to hear more specifics about issues you encountered using his Extender. I would think you could write your own parser using the WB CLR and .net assemblies. But you are also interested in changing 'values' [if I read your initial post correctly] which would imply an xml editor of sorts. Thanks for providing the sample .xml - can take a stab at it.


[EDIT]
from Tech DB


https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/dotNet/System_XML+ReadXmlFile~Sample.txt

Title: Re: Read data from an XML file.
Post by: JTaylor on May 22, 2023, 05:59:26 AM
I will try to take a look soon.  If you are wanting to change your XML, my extender is not a good choice though.  Perhaps the following will help provide a solution.

Jim

Code (winbatch) Select



;https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms754585(v=vs.85)


#DefineFunction Load_MSXMLData(xtxt)

  MSXML                    = ObjectOpen("MSXML2.DOMDocument.6.0")
  MSXML.Async              = "False"
  MSXML.preserveWhiteSpace = "False"
  MSXML.validateOnParse    = "False"
  MSXML.resolveExternals   = "False"

  Loaded = MSXML.LoadXML(xtxt)
  If !Loaded Then
 
    If !IsDefined(stxt) Then stxt = ""
    xPE = MSXML.parseError
    strErrText = "Your XML Document failed to load due the following error.":@CRLF:"Error #: ":xPE.errorCode:": ":xPE.reason:"Line #: ":xPE.Line:@CRLF:"Line Position: ":xPE.linepos:@CRLF:"Position In File: ":xPE.filepos:@CRLF:"Source Text: ":xPE.srcText:@CRLF:"Document URL: ":xPE.url
    clipput(strErrText)
    Message("Error",strErrText)
    xtxt = ""
    Return
  End If
  ; Get root of document
  XML_Root = MSXML.documentElement
  Return XML_Root

#EndFunction

xtxt = FileGet("xml_test.xml")
XML_Root = Load_MSXMLData(xtxt)
loaded_txt = XML_Root.xml
Message("XML",loaded_txt)


Title: Re: Read data from an XML file.
Post by: td on May 22, 2023, 07:24:52 AM
The .Net System.Xml namespace with WinBatch CLR hosting should be able to perform what the OP requires. The C# examples on the page indicated by the MSFT link below provide a good starting point for a WIL script.

https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldocument?view=netframework-4.8.1 (https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmldocument?view=netframework-4.8.1)


[edit] Jim's COM Automation suggestion is also worth checking out. It can do most/all of what is needed and is likely easier to understand unless you are already familiar with dotNet script in WinBatch. You can dump the progid "MSXML2.DOMDocument.6.0" into The WIL Typeviewer to get some idea of the available properties and methods.
Title: Re: Read data from an XML file.
Post by: stanl on May 27, 2023, 06:32:35 AM
Here is some quickie PS code to parse the xml data OP provided with output attached. My thoughts were to quickly collect the properties, queue up any changes then just write back to the xml file with replace functions. Maybe a bit simplistic. Oh, and WB can easily call the PS code. I suspect as Jim suggested that MSXML and xpath could accomplish the same in pure WB.


#parse xml into bar-delimited text for properties
#change xml and txt output as needed
$file = "c:\temp\zombies.txt"
$data = "class|property|value" | out-file $file
[xml] $info = Get-Content -Path C:\temp\zombies.xml
$base = $info.entity_classes.entity_class
ForEach ($class in $base)
{
     $name = $class.name
     $props = $class.property
     ForEach ($prop in $props)
     {
        $data = $name + "|" +$prop.name + "|" + $prop.value
        $data | Out-File $file -Append
     }
}
Exit


Title: Re: Read data from an XML file.
Post by: stanl on May 28, 2023, 03:53:47 AM
Looks like I missed a step. Attached is output from updated snippet. The XML is more like Json and could be serialized easier if it was. Will try to move the logic into either  WB CLR or MSXML, time permitting.


#parse xml into bar-delimited text for properties
#change xml file/path and txt output as needed
$file = "c:\temp\zombies.txt"
if (Test-Path $file ) {Remove-Item $file}
$data = "class|property|value" | out-file $file
[xml]$info = Get-Content -Path C:\temp\zombies.xml
$base = $info.FirstChild
if ($base.HasChildNodes -eq $true )
{
   ForEach ($class in $base.ChildNodes)
   {
       $name = $class.name
       $props = $class.property
       $grps = $class.effect_group
       ForEach ($prop in $props)
       {
          $data = $name + "|" +$prop.name + "|" + $prop.value
          $data | Out-File $file -Append
       }
       if ($grps.HasChildNodes -eq $true)
       {
          ForEach ($grp in $grps.ChildNodes)
          {
             $data = $name + "|" +$grp.name + "|" + $grp.value
             $data | Out-File $file -Append
          }
       }


   }
}
Exit