XPath Explained

From 7 Days to Die Wiki
Jump to: navigation, search
Some items' or groups' chance to drop changes according to the player's gamestage. Here you can see those values for any gamestage you want using the little box below. Just type the gamestage you want in the box and press the Apply!-button. The values should change immediately, if the chance is different.

Current game stage: 1

Introduced in Alpha 17, new modding hooks were made available to manipulate XML without directly modifying the base XML files.

This page will go over the xpath implementation, and provide examples on common syntax and tasks.

What is XPath?[edit | edit source]


XPath is a method of path expressions that can select nodes, or node-sets in an XML Document. An xpath expression navigates through an XML document, finding nodes and attributes that you are looking for.

The implementation in 7 Days to Die allows a way of adding, changing, or removing XML lines and nodes, without directly editing the XML files, using xpath to find the nodes we want changed.

This means we can change individual attributes in the XML, add new ones and remove existing ones.

For more information on xpath, please visit the w3schools.com

This Post was generated from information from this forum post.

XPath Syntax[edit | edit source]


XPath may look a bit intimidating when you are not familiar with it. This overview will break down what an xpath looks like when used against the XML files for 7 Days to Die.

An xpath format looks like this:

To find a node:

xpath="/rootNode/node"

To find a property:

xpath="/rootNode/node/property"

To find a attribute:

xpath="/rootNode/node/@attribute"


Those are very broad examples, but you can fine tune the syntax and only return the results you want.

<rootNode>
    <node name='MyOtherNode'>
    </node>
     <node name='MyNode'>
    </node>
</rootNode>

If you just wanted to access the MyNode, you can add conditions to your xpath:

xpath="/rootNode/node[@name='MyNode']/@attribute


XPath Examples[edit | edit source]


Here are some xpath examples, and what they'll find, using the vanilla XML files from Alpha 17 experimental release.

File: Data/Config/loot.xml


<lootcontainers>
     <!-- Other loot container lines, removed for clarity -->
     <!-- minibike storage -->
     <lootcontainer id="62" count="0" size="4,3" sound_open="UseActions/open_shopping_basket" open_time="0" sound_close="UseActions/close_shopping_basket" loot_quality_template="baseTemplate">
     </lootcontainer>
     <!-- other loot container lines, removed for clarity -->
</lootcontainers>

If we wanted to grab a reference to size="4,3", our xpath would look like this:

xpath="/lootcontainers/lootcontainer[@id='62']/@size"

If we want to grab a reference to open_time:

xpath="/lootcontainers/lootcontainer[@id='62']/@open_time"


Here is a more complicated example of the items.xml.

File: Data/Config/items.xml


<items>
	<item name="meleeBoneShiv">
		<property name="Tags" value="knife,melee,light,weapon,meleeWeapon,perkDeepCuts,perkTheHuntsman"/>
		<property name="DisplayType" value="melee"/>
		<property name="SoundDestroy" value="wooddestroy1"/>
		<property class="Action0">
			<property name="Class" value="DynamicMelee"/>
			<property name="Damage_type" value="Slashing"/>
        <!-- Snip the rest of the file -->

If we want to grab a reference to what Tags a meleeBoneShiv has:

xpath="/items/item[@name='meleeBoneShiv']/property[@name='Tags']/@value

The above xpath line reads: "Under the Items node, look for the item with the name meleeBoneShiv, which has a property with the name of Tags, and look for the value attribute"


XPath Commands[edit | edit source]

The above examples were to show how we can reference individual values. Alone, those references don't do anything. For those, we need to specify which xpath command we want to use. There are 5 primary xpath commands, with the first three being the most common ones to use.

set[edit | edit source]

The set command is used to change individual attributes.

If we wanted to change the size of the lootcontainer from 4,3, we would use the following format:

<set xpath="/lootcontainers/lootcontainer[@id='62']/@size">5,3</set>
removeattribute[edit | edit source]

The removeattributes is used to remove an existing attribute from an XML node

If we wanted to add a remove attribute called "author" on the meleeBoneShiv, we would do this:

 <removeattribute xpath="/items/item[@name='meleeBoneShiv']/@author" />

The result line would be:

<item name="meleeBoneShiv" >
setattribute[edit | edit source]

The setattribute is used to add a new attribude to an XML node

If we wanted to add a new attribute called "author" on the meleeBoneShiv, we would do this:

 <setattribute xpath="/items/item[@name='meleeBoneShiv']" name="author">sphereii</setattribute>

The result line would be:

<item name="meleeBoneShiv" author="sphereii" >
append[edit | edit source]

The append command is used to add either more nodes or more attribute values.

If we wanted to add another tag to the meleeBoneShiv, we would use the following format to add to the existing value:

<append xpath="/items/item[@name='meleeBoneShiv']/property[@name='Tags']/@value">,MyNewTag</append>

The resulting line would be:

<property name="Tags" value="knife,melee,light,weapon,meleeWeapon,perkDeepCuts,perkTheHuntsman,MyNewTag"/>


Append can also add blocks of code too. The following append command would add a new item at the bottom of the items root node:

<append xpath="/items">
       <item name="MyNewItem">
           <property name="Extends" value="meleeBoneShiv" />
       </item>
 </append>

Remove[edit | edit source]

The remove command is used to remove nodes or attributes.

If we wanted to remove the Tags off of the meleeBoneShiv, we would use it in this way:

<remove xpath="/items/item[@name='meleeBoneShiv']/property[@name='Tags']" />

To remove the meleeBoneShiv completely:

<remove xpath="/items/item[@name='meleeBoneShiv']" />


insertAfter[edit | edit source]

Much like append, insertAfter will add nodes and attributes after the selected xpath.

The snippet bellow allows you to add in the new panel in the windowVehicleStats window, after the rect called 'content', in the XUi/windows.xml:

<insertAfter xpath="/windows/window[@name='windowVehicleStats']/rect[@name='content']" >
	<panel pos="240, 0" style="header.panel">			
		<sprite style="header.icon" sprite="ui_game_symbol_add"/>
		<label style="header.name" text="COMBINE" text_key="xuiCombine"/>
	</panel>
</insertAfter>


insertBefore[edit | edit source]

Much like insertAfter, insertBefore will add nodes and attributes before the selected xpath.

The snippet below does nearly the exact same thing as the above insertAfter, however, it will add the panel before the rect called 'content'.

<insertBefore xpath="/windows/window[@name='windowVehicleStats']/rect[@name='content']" >
	<panel pos="240, 0" style="header.panel">			
		<sprite style="header.icon" sprite="ui_game_symbol_add"/>
		<label style="header.name" text="COMBINE" text_key="xuiCombine"/>
	</panel>
</insertBefore>

In most places, using the append command would be suitable for our needs. However, certain places, we want to make sure that we've added the code in the right place. For example, if you are extending from a block, you'll want to be sure that your new code is added below the master block.

XPath Conditions[edit | edit source]

Up until now, we've just been covering how to find xpath using direct matches (@name='toolbelt'), but xpath can provide us with more flexibility. Most of the time, you will not need these advanced conditionals, but be aware they exist for some more complex things you want to try.

starts-with( s1, s2 ) - Matches if s1 starts with whatever word you put in s2. In this example, @name is s1, and 'zombieTemp' is s2
<set xpath="/entity_classes/entity_class[starts-with(@name, 'zombieTemp')]/property[@name='Class']/@value">EntityZombieSDX, Mods</set>
ends-with( s1, s2 ) - Matches if s1 ends with whatever word you put in s2. In this example, @name is s1, and 'lateMale' is s2
<set xpath="/entity_classes/entity_class[ends-with(@name, 'lateMale')]/property[@name='Class']/@value">EntityZombieSDX, Mods</set>
contains( s1, s2 ) - Similar to starts-with, but s1 just needs to have some kind of match.
<set xpath="/entity_classes/entity_class[contains(@name, 'Template')]/property[@name='Class']/@value">EntityZombieSDX, Mods</set>
not - Flips the conditions around.
<set xpath="/entity_classes/entity_class[not (contains(@name, 'zombie'))]/property[@name='Class']/@value">EntityZombieSDX, Mods</set>

This would change every entity_class that does not contain the name zombie.

Another example:

<set xpath="/items/item[starts-with(@name, 'drinkJar') and not(contains(@name, 'Empty'))]/property[@name='Stacknumber']/@value">64</set>
and - Multi conditions. We used this above in the magazine_items, but we didn't explicitly type it out. An examples mean the same thing:
<set xpath="/items/item/property[@class='Action0']/property[@name='Magazine_items' and @value='9mmBullet']/@value">9mmBullet,NoAmmo</set>
or - Multi conditions, but only needs to match one. In the below example, it'll only make changes if the property name is magazine_items OR if the value is a 9mm bullet.
<set xpath="/items/item/property[@class='Action0']/property[@name='Magazine_items' or @value='9mmBullet']/@value">9mmBullet,NoAmmo</set>