Ludeon Forums

RimWorld => Mods => Help => Topic started by: K4nna on May 23, 2022, 11:37:32 PM

Title: xpath syntax for multiple selection
Post by: K4nna on May 23, 2022, 11:37:32 PM
Hi,

How is the correct syntax for my xpath please?

<xpath>/Defs/ThingDef[ ??? ]</xpath>

I want to select all ThingDef who have <minifiedDef>MinifiedThing</minifiedDef>, but who don't have <compClass>CompQuality</compClass> (select all the minifiable buildings who don't have quality).

I tried various things without find the good one :/


Also, can I use PatchOperation to add a new node who use the same value of another node? (add <WorkToMake> with the same value of <WorkToBuild>). I think no, but maybe...?
Title: Re: xpath syntax for multiple selection
Post by: Multistream on May 24, 2022, 03:36:02 AM
<xpath>Defs/ThingDef[minifiedDef="MinifiedThing" and (not(comps/li/compClass="CompQuality"))]</xpath>

On the second question, copying or storing a value isn't possible in vanilla, you can do that with XML Extensions mod if you are fine with using it as a dependency
Title: Re: xpath syntax for multiple selection
Post by: K4nna on May 24, 2022, 03:53:53 AM
Thank you, the syntax is good.
But it doesn't works as intended, I think I have to filter by 'Abstract="True"'
Title: Re: xpath syntax for multiple selection
Post by: K4nna on May 24, 2022, 05:09:43 AM
So, (not(Abstract="True")) doesn't work. I have almost the same result by using (not(@Name="FurnitureBase")) (only the 'drape' is not patched, without mods). But it could be good to know the syntax for filter Abstract.

Edit: I also search to add a condition 'don't have <CostList>', (not(CostList)) doesn't work :/
Title: Re: xpath syntax for multiple selection
Post by: Multistream on May 25, 2022, 11:49:44 AM
Quote from: K4nna on May 24, 2022, 03:53:53 AM
Thank you, the syntax is good.
But it doesn't works as intended, I think I have to filter by 'Abstract="True"'
Abstract is an attribute like Name so it needs @ before it, like this:  (not(@Abstract="True")).
In (not(CostList)) you have a wrong capitalisation, its (not(costList)).

So looking at what you want to do, it won't select the desired defs in a number of cases where an abstract base defines <minifiedDef>MinifiedThing</minifiedDef>, and a concrete def that inherits from it defines <compClass>CompQuality</compClass>. They are still separate defs, each one of them is checked individually only, so "and" won't work.
There are still ways to do it almost completely reliably, for example all defs with minifiedDef must have statBases/Mass that is inherited much more rarily, but you would need to add checks if the def is a building because items can also have mass stat. You would probably have to do more than that though.

I recommend asking this question on rimworld discord, the modding channel is very active there. It also has a bot you can access with !xpath command, it lets you instantaneously test what a given xpath will select in vanilla rimworld.
Title: Re: xpath syntax for multiple selection
Post by: K4nna on May 25, 2022, 12:59:07 PM
I will try it tomorrow, but it's weird, I'm sure that I tried (not(@Abstract="True")).
For costList, I'm not sure if I copied/paste from file or not.

With that I can already do my patch with full compatibility with buildings from mods I think.
If I look for <minifiedDef>MinifiedThing</minifiedDef>, it's because the mod I patch looks for buildings this way (via C#).

Thank you again, I will look about discord another time.
Title: Re: xpath syntax for multiple selection
Post by: K4nna on May 26, 2022, 12:44:16 AM
So I used the good syntax, but it doesn't work as I think with the abstract thing and inheritance.
Even the costList I can't do it works...

<xpath>Defs/ThingDef[minifiedDef="MinifiedThing" and (not(comps/li/compClass="CompQuality")) and (not(@Abstract="True")) and (not(thingCategories="BuildingsSecurity")) and costList]</xpath>
Doesn't work   (I tried with only Abstract, or only costList...)

<xpath>Defs/ThingDef[minifiedDef="MinifiedThing" and (not(comps/li/compClass="CompQuality")) and (not(@Name="FurnitureBase")) and (not(thingCategories="BuildingsSecurity")) and (not(@ParentName="BuildingNaturalBase")) and (not(defName="AnimusStone")) and (not(defName="MonumentMarker"))]</xpath>
Works as I want (with additional patch for the 'drape')