xpath syntax for multiple selection

Started by K4nna, May 23, 2022, 11:37:32 PM

Previous topic - Next topic

K4nna

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...?

Multistream

#1
<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

K4nna

Thank you, the syntax is good.
But it doesn't works as intended, I think I have to filter by 'Abstract="True"'

K4nna

#3
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 :/

Multistream

#4
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.

K4nna

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.

K4nna

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')