[TUTORIAL] XML Patch Guide

The place to discuss scripting and game modifications for X Rebirth.

Moderators: Scripting / Modding Moderators, Moderators for English X Forum

theqmann
Posts: 19
Joined: Fri, 21. Jan 11, 21:47
x4

[TUTORIAL] XML Patch Guide

Post by theqmann » Sun, 24. Nov 13, 19:19

So I read through the IETF XML Patch standard and wanted to share my findings on the possibilities for the xml patch files. Examples sourced from the excellent modding guide, the IETF spec, and the xmlpatch library.

Every xml patch file needs to have the header line and the diff root tag:

Code: Select all

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

<diff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > 

   ...

</diff>
There are 3 types of operations that can be performed:
  • add - add a block of xml text
    replace - replace a block of xml text
    remove - remove a block of xml text
After picking one of these, the block of xml that is to be modified needs to be selected with the "sel" command. The sel argument node must unambiguously describe a single node.

There is a multi-node selection parameter (msel) which is not in the IETF spec, but is supported by the xmlpatch library. I do not know if X supports it, however, so I'd recommend making multiple unique entries instead of a multiple selection.

Some basic examples

All of these will use this basic source file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
  </bar>
</root>
Add:

Patch

Code: Select all

  <add sel="root/bar">
    <foo a="3"/>
  </add>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
    <foo a="3"/>
  </bar>
</root>

Replace:

Patch

Code: Select all

  <replace sel="root/bar/foo[@a='1']">
    <foo a="3"/>
  </replace>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="3"/>
    <foo a="2"/>
  </bar>
</root>
Remove:

Patch

Code: Select all

  <remove sel="root/bar/foo[@a='1']"/>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="2"/>
  </bar>
</root>
Advanced Parameters

The add command has three attributes that can be used:
  • sel
    type
    pos
The replace command has only one attribute:
  • sel
The remove command has two attributes:
  • sel
    ws
Here's some examples.

Add an attribute

Patch

Code: Select all

  <add sel="root/bar" type="@cat">3</add>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar cat="3">
    <foo a="1"/>
    <foo a="2"/>
  </bar>
</root>
Add something before

Patch

Code: Select all

  <add sel="root/bar" pos="before">
    <foo a="3"/>
  </add>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <foo a="3"/>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
  </bar>
</root>
Add something as first child node

Patch

Code: Select all

  <add sel="root/bar" pos="prepend">
    <foo a="3"/>
  </add>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="3"/>
    <foo a="1"/>
    <foo a="2"/>
  </bar>
</root>
Add something as last child node (default)

Patch

Code: Select all

  <add sel="root/bar">
    <foo a="3"/>
  </add>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
    <foo a="3"/>
  </bar>
</root>
Wildcard Add #1

Patch

Code: Select all

  <add sel="*/bar">
    <foo a="3"/>
  </add>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
    <foo a="3"/>
  </bar>
</root>
Wildcard Add #2

Patch

Code: Select all

  <add sel="*/foo[@a='1']">
    <cat a="3"/>
  </add>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1">
      <cat a="3"/>
    </foo>
    <foo a="2"/>
  </bar>
</root>
Wildcard Replace

Patch

Code: Select all

  <replace sel="*/foo[@a='1']">
    <cat a="3"/>
  </replace>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <cat a="3"/>
    <foo a="2"/>
  </bar>
</root>
Replace an attribute

Patch

Code: Select all

  <replace sel="root/bar/foo[@a='1']/@a">3</replace>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="3"/>
    <foo a="2"/>
  </bar>
</root>
Remove an attribute

Patch

Code: Select all

  <remove sel="root/bar/foo[@a='1']/@a"/>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo/>
    <foo a="2"/>
  </bar>
</root>
Remove node with plaintext (a.k.a. whitespace text)

Source

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1">Some text here</foo>
    <foo a="2"/>
  </bar>
</root>
Patch

Code: Select all

  <remove sel="root/bar/foo[@a='1']" ws="after"/>
Result

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="2"/>
  </bar>
</root>

{ 10.12.2013 - added xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" in diff-node to avoid Errors in Debuglog - UniTrader
Last edited by theqmann on Tue, 26. Nov 13, 01:33, edited 1 time in total.

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Sun, 24. Nov 13, 19:25

this should definietly be pinned or at least linked in the stickies :) didnt know how to modify attributes before, very useful ;)

EDIT: giving this hint a more prominent Position:
hint for shortening if you just want to add things directly under the root node:

Source File:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
  </bar>
</root>

Extension File: (NO DIFF!!)

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar2>
    <foo a="5"/>
    <foo a="6"/>
  </bar2>
</root>
(virtual) result file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
  </bar>
  <bar2>
    <foo a="5"/>
    <foo a="6"/>
  </bar2>
</root>
not sure if its in the rfcs, but as you can see the xmls are merged (seems to cause trouble for others)
note that it only works directly under the root node, in any other case you have to use diffs (except where it doesnt matter if a node under the root node exists twice, like in t-files)
Last edited by UniTrader on Sun, 1. Dec 13, 13:00, edited 1 time in total.
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

theqmann
Posts: 19
Joined: Fri, 21. Jan 11, 21:47
x4

Post by theqmann » Sun, 24. Nov 13, 19:32

I also wanted to mention that you can check for any error messages if you add this to your command line arguments:

-debug all -logfile debug_rebirth.log

And look near the top of the resulting log file for error messages.

The file itself is stored in one directory up from where the savegames are located.

Skeeter
Posts: 3664
Joined: Thu, 9. Jan 03, 19:47
x3

Post by Skeeter » Sun, 24. Nov 13, 19:51

Im having trouble understanding how to say from character_components.xml from assests/character folder.

How to change

Code: Select all

<!-- Decoration - Security Guard -->
   <component name="character_deco_security_guard_01" class="npc">
    <size>
      <max x="0.5" y="1.0" z="0.5"/>
      <center x="0.0" y="1.0" z="0.0"/>
    </size>
    <connections>
      <connection name="attachments" tags="attachment" value="0" optional="1" />
    </connections>
    <properties>
      <boneroot name="Bip01" />
      <skeleton>
        <root name="bip01" />
        <head name="bip01 head" />	<!-- used for lookat controller -->
        <righteye name="right eye dummy" />	<!-- used for lookat controller -->
        <lefteye name="left eye dummy" />	<!-- used for lookat controller -->
      </skeleton>
      <animations>
            <animation name="decoration01" ref="assets/characters/animations/ani_decoration_security_01" />
      </animations>
      <sequences>
        <sequence type="idle" behavior="generic">
          <transitions>
            <transition start="standing" end="standing" animation="decoration01" />
          </transitions>
        </sequence>
      </sequences>
    </properties>
  </component> 
Into

Code: Select all

<!-- Decoration - Security Guard -->
   <component name="character_deco_security_guard_01" class="npc">
    <size>
      <max x="0.5" y="1.0" z="0.5"/>
      <center x="0.0" y="1.0" z="0.0"/>
    </size>
    <connections>
      <connection name="attachments" tags="attachment" value="0" optional="1" />
    </connections>
    <properties>
      <boneroot name="Bip01" />
      <skeleton>
        <root name="bip01" />
        <head name="bip01 head" />	<!-- used for lookat controller -->
        <righteye name="right eye dummy" />	<!-- used for lookat controller -->
        <lefteye name="left eye dummy" />	<!-- used for lookat controller -->
      </skeleton>
      <animations>
        <animation name="dancing01" ref="assets/characters/argon/animations/anim_decoration_dance" />
      </animations>
      <sequences>
        <sequence type="idle" behavior="generic">
          <transitions>
            <transition start="standing" end="standing" animation="dancing01" />
          </transitions>
        </sequence>
      </sequences>
    </properties>
  </component> 
Changing the variables of animation into dancing01 and the ref next to it, and then the transitions bit dancing01. from the originals.

Im not sure im referencing the source file properly like but i know the change would work because i tried the brute force method of using the original file edited and changing it to pck format and it works i just have trouble doing this patch to replace some words for this file thats all so any help would be appreciated.

Code: Select all

<diff>
  <!--  securityguardnpc -->
  <replace sel="/components/component[@name='character_deco_security_guard_01']/animations/animation[@name='decoration01'][@ref='assets/characters/animations/ani_decoration_security_01']/sequences/sequence/transitions/transition[@animation='decoration01']">
  
        <animation name="dancing01" ref="assets/characters/argon/animations/anim_decoration_dance" />
      
              
        <transition start="standing" end="standing" animation="dancing01" />
          
        
		</replace>
</diff>
[ external image ]
7600x cpu 5.4ghz 32gb DDR5 5600mhz 6700XT 32" 1440p mon

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Sun, 24. Nov 13, 19:53

hint for shortening if you just want to add things directly under the root node:

Source File:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
  </bar>
</root>

Extension File: (NO DIFF!!)

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar2>
    <foo a="5"/>
    <foo a="6"/>
  </bar2>
</root>
(virtual) result file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <bar>
    <foo a="1"/>
    <foo a="2"/>
  </bar>
  <bar2>
    <foo a="5"/>
    <foo a="6"/>
  </bar2>
</root>
not sure if its in the rfcs, but as you can see the xmls are merged (seems to cause trouble for others)
note that it only works directly under the root node, in any other case you have to use diffs (except where it doesnt matter if a node under the root node exists twice, like in t-files)
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Sun, 24. Nov 13, 20:06

to Skeeter:

Code: Select all

<diff>
<replace sel='###/component[@name="character_deco_security_guard_01"]/properties/animations/animation[@name="dancing01"]/@ref'>assets/characters/argon/animations/anim_decoration_dance</replace>
<replace sel='###/component[@name="character_deco_security_guard_01"]/properties/sequences/sequence[@type="idle"]/transtions/transition[@animation="decoration01"]/@animation'>dancing01</replace>
</diff>
should do the trick ;) (was a bit more precise than necesary in pointing to nodes in case another extension adds something there, too.. keep it as specific as possible ;) )
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

User avatar
Observe
Posts: 5079
Joined: Fri, 30. Dec 05, 17:47
xr

Post by Observe » Sun, 24. Nov 13, 20:11

UniTrader wrote:this should definietly be pinned
Seconded or thirded or whatever number is next in line for accolades. :)

Skeeter
Posts: 3664
Joined: Thu, 9. Jan 03, 19:47
x3

Post by Skeeter » Sun, 24. Nov 13, 20:16

Thanks, i tried copy and paste what u did but it still didnt work?

What does the ### do, just me to fill or somit else as i duno what to put there.
[ external image ]
7600x cpu 5.4ghz 32gb DDR5 5600mhz 6700XT 32" 1440p mon

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Sun, 24. Nov 13, 20:22

Skeeter wrote:Thanks, i tried copy and paste what u did but it still didnt work?

What does the ### do, just me to fill or somit else as i duno what to put there.
ops, i forgot.. these are the nodes which you didnt copy since it seemed you just copied a part of the file, not the whole..
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

User avatar
ybeline
Posts: 83
Joined: Sun, 22. Aug 10, 13:55
x4

Re: [TUTORIAL] XML Patch Guide

Post by ybeline » Sun, 24. Nov 13, 20:24

Hello,

theqmann wrote:So I [...] wanted to share my findings on the possibilities for the xml patch files
Sir, I really want to thank you! :)
I had troubles to understand some of those 'Advanced Parameters' and you've described them very well, with easy to use examples.
This has to be pinned somewhere.

Again, many thanks!



Regards,

ybeline

Mad_Joker
Posts: 274
Joined: Sun, 14. May 06, 11:21
x3

Post by Mad_Joker » Sun, 24. Nov 13, 20:30

UniTrader wrote:to Skeeter:

Code: Select all

<diff>
<replace sel='###/component[@name="character_deco_security_guard_01"]/properties/animations/animation[@name="dancing01"]/@ref'>assets/characters/argon/animations/anim_decoration_dance</replace>
<replace sel='###/component[@name="character_deco_security_guard_01"]/properties/sequences/sequence[@type="idle"]/transtions/transition[@animation="decoration01"]/@animation'>dancing01</replace>
</diff>
should do the trick ;) (was a bit more precise than necesary in pointing to nodes in case another extension adds something there, too.. keep it as specific as possible ;) )
Actually, I disagree about the "keep it specific". First, if you make it less specific, it is less likely to break with a future patch. It is also less likely to conflict with other mods. That is because these diff patches are applied one after another. That means if you depend in your path on a certain node to be there (let's say something like /do_else[2], i.e. the second do_else in some branch) and someone decides to put another do_else before that, your mod will break. Therefore, I like to do things like this:

Code: Select all

<replace sel="//open_conversation_menu[@menu='TraderMenu']/preceding-sibling::add_conversation_view/@view">closeupdetailmonitor</replace>
So I try to keep it as general as possible, without making it ambiguous.

PS: // searches in all subnodes, so the above searches the whole file for open_conversation_menu with a add_conversation_view before it, and replaces one attribute. This way, I get maximum compatibility, without too much impact.

EDIT: I am of course aware, that my code can also break, e.g. if someone decides to put another open_conversation_menu that matches my expression anywhere in the file, it will break. But yeah, 100% compatibility is just impossible.

Skeeter
Posts: 3664
Joined: Thu, 9. Jan 03, 19:47
x3

Post by Skeeter » Sun, 24. Nov 13, 21:00

Thx guys, got it working. :)

I will post the mod on the forum in a min if u wana check it out.
[ external image ]
7600x cpu 5.4ghz 32gb DDR5 5600mhz 6700XT 32" 1440p mon

theqmann
Posts: 19
Joined: Fri, 21. Jan 11, 21:47
x4

Post by theqmann » Mon, 25. Nov 13, 18:07

can someone make this post sticky?

User avatar
nonnex
Posts: 366
Joined: Wed, 28. Aug 13, 12:42
x4

Post by nonnex » Mon, 25. Nov 13, 18:50

Good work. Thank you.

MutantDwarf
Posts: 711
Joined: Tue, 20. Jun 06, 02:29
x4

Post by MutantDwarf » Mon, 25. Nov 13, 21:10

It really should be mentioned in the first post that all selection arguments need to point to a unique node; there can't be any ambiguity, and if there is the whole node will just be ignored and left unchanged.

BlueWulv
Posts: 238
Joined: Sat, 7. Feb 04, 17:06
x4

Post by BlueWulv » Tue, 26. Nov 13, 00:17

+1 for sticky

And thank you :)

theqmann
Posts: 19
Joined: Fri, 21. Jan 11, 21:47
x4

Post by theqmann » Tue, 26. Nov 13, 01:28

Good idea on the unique requirement. I'll put in some text on that.

Skeeter
Posts: 3664
Joined: Thu, 9. Jan 03, 19:47
x3

Post by Skeeter » Tue, 26. Nov 13, 23:08

Im a little lost with how you add things to certain places. I want to expand my mod but instead of replacing i want to add lines to certain sections the examples on the first post are a bit vague for adding into a complex section well complex as in more than a few things.

So how would i for example add this to this.

This

Code: Select all

<animation name="dancing01" ref="assets/characters/argon/animations/anim_decoration_dance" />

To this.

Code: Select all

<component name="character_deco_security_guard_01" class="npc">
    <size>
      <max x="0.5" y="1.0" z="0.5"/>
      <center x="0.0" y="1.0" z="0.0"/>
    </size>
    <connections>
      <connection name="attachments" tags="attachment" value="0" optional="1" />
    </connections>
    <properties>
      <boneroot name="Bip01" />
      <skeleton>
        <root name="bip01" />
        <head name="bip01 head" />	<!-- used for lookat controller -->
        <righteye name="right eye dummy" />	<!-- used for lookat controller -->
        <lefteye name="left eye dummy" />	<!-- used for lookat controller -->
      </skeleton>
      <animations>
            <animation name="decoration01" ref="assets/characters/animations/ani_decoration_security_01" />
      </animations>
      <sequences>
        <sequence type="idle" behavior="generic">
          <transitions>
            <transition start="standing" end="standing" animation="decoration01" />
          </transitions>
        </sequence>
      </sequences>
    </properties>
  </component> 
So it looks like this when it works.

Code: Select all

<component name="character_deco_security_guard_01" class="npc">
    <size>
      <max x="0.5" y="1.0" z="0.5"/>
      <center x="0.0" y="1.0" z="0.0"/>
    </size>
    <connections>
      <connection name="attachments" tags="attachment" value="0" optional="1" />
    </connections>
    <properties>
      <boneroot name="Bip01" />
      <skeleton>
        <root name="bip01" />
        <head name="bip01 head" />	<!-- used for lookat controller -->
        <righteye name="right eye dummy" />	<!-- used for lookat controller -->
        <lefteye name="left eye dummy" />	<!-- used for lookat controller -->
      </skeleton>
      <animations>
            <animation name="decoration01" ref="assets/characters/animations/ani_decoration_security_01" />
      <animation name="dancing01" ref="assets/characters/argon/animations/anim_decoration_dance" />
      </animations>
      <sequences>
        <sequence type="idle" behavior="generic">
          <transitions>
            <transition start="standing" end="standing" animation="decoration01" />
          </transitions>
        </sequence>
      </sequences>
    </properties>
  </component> 
In the animation node, i want the line there as seen above. Soon as i figure this out i can add to there and a few new lines in transitions.

I thought it would be like

Code: Select all

<add sel='//component[@name="character_deco_security_guard_01"]/properties/animations/@animation'> <animation name="dancing01" ref="assets/characters/argon/animations/anim_decoration_dance" /> </add>
But im guessing im wrong because the line isnt in black its in blue still when using notepad ++, when i did the replace command for a word it was black when it worked when i got help before.
[ external image ]
7600x cpu 5.4ghz 32gb DDR5 5600mhz 6700XT 32" 1440p mon

BlueWulv
Posts: 238
Joined: Sat, 7. Feb 04, 17:06
x4

Post by BlueWulv » Tue, 26. Nov 13, 23:26

I am not sure but maybe:

Code: Select all

<add sel='/component[@name="character_deco_security_guard_01"]/properties/animations>
<animation name="dancing01" ref="assets/characters/argon/animations/anim_decoration_dance" />
</add>
Or there is a syntax error before this line?
But im guessing im wrong because the line isnt in black its in blue
Sounds a little bit like an existing comment tag was not closed:

Code: Select all

<!--
vs

Code: Select all

<!--
-->

Skeeter
Posts: 3664
Joined: Thu, 9. Jan 03, 19:47
x3

Post by Skeeter » Wed, 27. Nov 13, 00:19

Tried and it didnt work.

Code: Select all

<diff> 

<add sel='//component[@name="character_deco_security_guard_01"]/properties/animations'>
    	<animation name="dancing01" ref="assets/characters/argon/animations/anim_decoration_dance" />
	    <animation name="a_facepalm01" ref="assets/characters/animations/anim_a_facepalm_ar_fe_generic_01" lookat="0" />
</add>

 
<add sel='//component[@name="character_deco_security_guard_01"]/properties/sequences/sequence/transitions'>
            <transition start="standing" end="standing" animation="dancing01" />
			<transition start="standing" end="standing" animation="a_facepalm01" />
</add>
 
</diff>
This is my attempt so far, i think im close but still doesnt seem to be putting them 2 lines in animations section and 2 lines in transitions section. :( I know the mod works as i did the pck way to force it but i would rather not use that method and to try to rely more on add or replace patch methods.

Anyhow, any further help would be appreciated. :)
[ external image ]
7600x cpu 5.4ghz 32gb DDR5 5600mhz 6700XT 32" 1440p mon

Post Reply

Return to “X Rebirth - Scripts and Modding”