How make xml Condition List more compact

I’m trying to cut down on my xml so that it’s more short/compact, as requested by my team.

The format below winds up being about 1000 lines long with all my build processes, but I’m pretty sure there’s a way to make it more compact. Is there a way to shorten the Condition or SuccessCriteria tag so that I use attributes like the surrounding xml? I need to account for cases with multiple conditions or SuccessCriteria, as shown below. From my search, same attribute pairs multiple times, it doesn’t look like I can have attributes with the same name, which this would be if I do something similar to what I have in the top of the process tag.

I need the Condition name/value to always be called that because I’m using LINQ to read the xml and those conditions and success criteria get put in a list that I iterate through. Plus sometimes I have 1 condition pair, but sometimes it’s 2, and in the future it could be 3. Similarly with SuccessCriteria.

<?xml version="1.0" encoding="UTF-8"?>
<BuildVerficationRoot>
<Configuration>
    <Value Name="emailFrom">SCM-BuildCoordinator@co.com</Value>
    <Value Name="admin_list">me@co.com</Value> 
    <Value Name="verboseLogFileName">VerifyBuildVerbose.txt</Value>
    <Value Name="statsLogProcessVerFileName">ProcessStatusVerificationStats.txt</Value>
    <Value Name="project">proj</Value>
    <Value Name="version">1.0</Value>
</Configuration>
<BuildVerification>
    <codeFreezeTime>19:00</codeFreezeTime>
    <build machine="mach-1">
            <Process name="Proc1"
                startTimeHeader="StartTime"
                endTimeHeader="EndTime"
                failureColumns="ErrorDescription">
                    <Condition
                        name='VersionFile' value="\view\proj\filename1.cs">
                    </Condition>
                    <Condition
                        name='VersionFile' value="\view\proj\filename2.cs">
                    </Condition>
                    <SuccessCriteria>
                        <field>Status</field>
                        <comparison>equal</comparison> 
                        <value>Success</value>
                    </SuccessCriteria>
            </Process>
</build>
<build machine="co.net\share\folder\folder2\">
            <Process name="Stats1"
                startTimeHeader="Time"
                endTimeHeader="Time"
                failureColumns="">
                    <Condition
                            name='VersionId' value="1.0">
                    </Condition>
                    <Condition
                        name='MediaType' value="Incr">
                    </Condition>
                    <SuccessCriteria>
                        <field>Status</field>
                        <comparison>equal</comparison> 
                        <value>Success</value>
                    </SuccessCriteria>
            </Process>
            <Process name="MediaStats"
                startTimeHeader="EndTime"
                endTimeHeader="EndTime"
                failureColumns="">
                        <Condition
                            name1='Ver1' name2="Ver2">
                        </Condition>
                    <SuccessCriteria>
                        <field>MediaType</field>
                        <comparison>equal</comparison> 
                        <value>Full</value>
                    </SuccessCriteria>
            </Process>
            <Process name="MediaStats"
                startTimeHeader="EndTime"
                endTimeHeader="EndTime"
                failureColumns="">
                        <Condition
                            name1='Ver1' name2="Ver2">
                        </Condition>
                    <SuccessCriteria>
                        <field>MediaType</field>
                        <comparison>equal</comparison> 
                        <value>Incr</value>
                    </SuccessCriteria>
            </Process>
            <Process name="ProcessingStats"
                startTimeHeader="StartTime"
                endTimeHeader="EndTime"
                failureColumns="">
                    <Condition
                        name='Project' value="1.0">
                    </Condition>
                    <SuccessCriteria>
                        <field>Deliverables</field>
                        <comparison>notEqual</comparison>
                        <value>""</value>
                    </SuccessCriteria>
                    <SuccessCriteria>
                        <field>InInstallers</field>
                        <comparison>notEqual</comparison>
                        <value>""</value>
                    </SuccessCriteria>
                    <SuccessCriteria>
                        <field>MakePackage</field>
                        <comparison>notEqual</comparison>
                        <value>""</value>
                    </SuccessCriteria>
                    <SuccessCriteria>
                        <field>Publish</field>
                        <comparison>notEqual</comparison>
                        <value>""</value>
                    </SuccessCriteria>
                        
            </Process>
        </build>
        
</BuildVerification>
</BuildVerficationRoot> 
    

I tried doing the following with the first Process, but get error:

c# System.Xml>XmlException: “name” is a duplicate attribute name.

<Process name="SpinFileVersionStats"
                startTimeHeader="StartTime"
                endTimeHeader="EndTime"
                failureColumns="ErrorDescription">
                    <Condition name='VersionFile' value="\view\proj\filename1.cs"
                               name='VersionFile2' value="\view\proj\filename2.cs"></Condition>
                    <SuccessCriteria>
                        <field>Status</field>
                        <comparison>equal</comparison> 
                        <value>Success</value>
                    </SuccessCriteria>
    </Process>

So my question is, is there a more compact way to show the same info in xml? I’m not talking about removing carriage returns around the Condition tags. Thanks!

To make your XML more compact while preserving the necessary information and addressing the issue of duplicate attributes, you can restructure the Condition and SuccessCriteria tags into a more compact format without duplicating attribute names. Here are a few approaches:


1. Combine Multiple Condition Tags into One

Instead of using multiple Condition tags, you can merge them into a single tag and use a delimiter to separate the name-value pairs.

<Condition values="VersionFile:\view\proj\filename1.cs;VersionFile:\view\proj\filename2.cs" />

2. Convert Condition to Attributes

If the number of conditions is known to be small and fixed, you can convert each condition into an attribute of the Process tag. Use unique attribute names to avoid duplication.

<Process name="Proc1"
         startTimeHeader="StartTime"
         endTimeHeader="EndTime"
         failureColumns="ErrorDescription"
         condition1="VersionFile:\view\proj\filename1.cs"
         condition2="VersionFile:\view\proj\filename2.cs">
    <SuccessCriteria>
        <field>Status</field>
        <comparison>equal</comparison> 
        <value>Success</value>
    </SuccessCriteria>
</Process>

3. Compact SuccessCriteria Using Attributes

For SuccessCriteria, you can use a single tag with attributes instead of separate child tags.

<SuccessCriteria field="Status" comparison="equal" value="Success" />

4. Combine SuccessCriteria Tags for Multiple Entries

If there are multiple SuccessCriteria, you can combine them into a single tag using delimiters or lists.

Example:

<SuccessCriteria 
    fields="Deliverables,InInstallers,MakePackage,Publish" 
    comparisons="notEqual,notEqual,notEqual,notEqual" 
    values="\"\",\"\",\"\",\"\"" />

Alternatively, if field-comparison-value relationships are more complex:

<SuccessCriteria criteria="Deliverables:notEqual:\"\",InInstallers:notEqual:\"\",MakePackage:notEqual:\"\",Publish:notEqual:\"\"" />

Final Example (Compact Version)

Here’s how your XML could look with these adjustments:

<?xml version="1.0" encoding="UTF-8"?>
<BuildVerificationRoot>
    <Configuration>
        <Value Name="emailFrom">SCM-BuildCoordinator@co.com</Value>
        <Value Name="admin_list">me@co.com</Value>
        <Value Name="verboseLogFileName">VerifyBuildVerbose.txt</Value>
        <Value Name="statsLogProcessVerFileName">ProcessStatusVerificationStats.txt</Value>
        <Value Name="project">proj</Value>
        <Value Name="version">1.0</Value>
    </Configuration>
    <BuildVerification>
        <codeFreezeTime>19:00</codeFreezeTime>
        <build machine="mach-1">
            <Process name="Proc1"
                     startTimeHeader="StartTime"
                     endTimeHeader="EndTime"
                     failureColumns="ErrorDescription"
                     conditions="VersionFile:\view\proj\filename1.cs;VersionFile:\view\proj\filename2.cs">
                <SuccessCriteria field="Status" comparison="equal" value="Success" />
            </Process>
        </build>
        <build machine="co.net\share\folder\folder2\">
            <Process name="Stats1"
                     startTimeHeader="Time"
                     endTimeHeader="Time"
                     failureColumns=""
                     conditions="VersionId:1.0;MediaType:Incr">
                <SuccessCriteria field="Status" comparison="equal" value="Success" />
            </Process>
            <Process name="ProcessingStats"
                     startTimeHeader="StartTime"
                     endTimeHeader="EndTime"
                     failureColumns=""
                     conditions="Project:1.0">
                <SuccessCriteria criteria="Deliverables:notEqual:\"\",InInstallers:notEqual:\"\",MakePackage:notEqual:\"\",Publish:notEqual:\"\"" />
            </Process>
        </build>
    </BuildVerification>
</BuildVerificationRoot>

Benefits of This Structure

  1. Compactness: Fewer lines of XML while preserving readability.
  2. Flexibility: Easy to parse with LINQ by splitting the conditions or criteria strings.
  3. Scalability: Supports multiple conditions and success criteria without duplicating attribute names.

Parsing with LINQ

You can parse these new structures in LINQ using string splitting for conditions and criteria.

Example LINQ code for conditions:

var conditions = processElement.Attribute("conditions")
    .Value
    .Split(';')
    .Select(cond => {
        var parts = cond.Split(':');
        return new { Name = parts[0], Value = parts[1] };
    })
    .ToList();

Let me know if you need help implementing this!