How to increase or decrease the percentage of XML Attribute Values by regex?



  • For example:

    <warrior>
    <level agility="50" constitution="75" intelligence="100" strength="120"/>
    </warrior>
    
    <mage>
    <level agility="75" constitution="50" intelligence="120" strength="100"/>
    </mage>
    

    Now, I want to increase “agility” by 20%, “constitution” by 10%, “intelligence” by 20% and “strength” by 10% for “warrior” and do the opposite of “mage”.
    I wonder if there are any plugins or methods to do that? When both have about 160 lines.



  • @Tư-Mã-Tần-Quảng

    It’s a common question, to which the answer is probably not.



  • @Tư-Mã-Tần-Quảng

    This can be done with an XSL transformation. Please follow these steps:

    1. Download msxsl.exe, a command line XSLT processor released by Microsoft, from >>> here <<<, or just google for msxsl.exe.

    2. Create a folder where to put:

    • your input XML file.
    • the XSL transformation file (see code below).
    • the batch script for automating the whole process (see code below).
    • *.ini files for every user whose data you want to change in the XML file.

    Code of the XSL file (save it as e.g. Transform.xsl):

    <?xml version="1.0" encoding="utf-8"?>
    
    <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <xsl:output
        method="xml"
        indent="yes"
        omit-xml-declaration="no"
        encoding="utf-8"
      />
    
      <xsl:param name="userName"/>
      <xsl:param name="agilityFactor"/>
      <xsl:param name="constitutionFactor"/>
      <xsl:param name="intelligenceFactor"/>
      <xsl:param name="strengthFactor"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="level">
        <xsl:choose>
          <xsl:when test="name(..)=$userName">
            <xsl:copy>
              <xsl:apply-templates select="@*"/>
    
              <xsl:attribute name="agility">
                <xsl:value-of select="@agility * $agilityFactor"/>
              </xsl:attribute>
    
              <xsl:attribute name="constitution">
                <xsl:value-of select="@constitution * $constitutionFactor"/>
              </xsl:attribute>
    
              <xsl:attribute name="intelligence">
                <xsl:value-of select="@intelligence * $intelligenceFactor"/>
              </xsl:attribute>
    
              <xsl:attribute name="strength">
                <xsl:value-of select="@strength * $strengthFactor"/>
              </xsl:attribute>
    
              <xsl:apply-templates select="node()"/>
            </xsl:copy>
          </xsl:when>
          <xsl:otherwise>
            <xsl:copy>
              <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    
    </xsl:transform>
    

    Code of the batch script (save it as e.g. Transform.cmd). Please note: You have to customize lines 3 to 6 to your needs.

    @echo off & setlocal
    
    set "MSXSL=<Path-To-msxsl.exe>"
    set "BaseDir=<Path-To-Folder-With-Input-Files>"
    set "XMLFile=%BaseDir%\<Name-Of-Your-XML-File>"
    set "XSLFile=%BaseDir%\<Name-Of-Your-XSL-File>"
    
    copy "%XMLFile%" "%XMLFile%.bak"
    
    for %%z in ("%BaseDir%\*.ini") do (
      for /f "usebackq tokens=1* delims==" %%a in ("%%~z") do (
        if /i "%%~a" equ "userName" set "UserName=%%~a='%%~b'"
        if /i "%%~a" equ "agilityFactor" set "NewAgility=%%~a=%%~b"
        if /i "%%~a" equ "constitutionFactor" set "NewConstitution=%%~a=%%~b"
        if /i "%%~a" equ "intelligenceFactor" set "NewIntelligence=%%~a=%%~b"
        if /i "%%~a" equ "strengthFactor" set "NewStrength=%%~a=%%~b"
      )
    
      call :ProcessUser
    )
    
    exit /b 0
    
    
    :ProcessUser
      set "Params=%NewAgility% %NewConstitution% %NewIntelligence% %NewStrength%"
      "%MSXSL%" "%XMLFile%" "%XSLFile%" -o "%XMLFile%" %UserName% %Params%
    exit /b 0
    

    Now you can create *.ini files for every user whose data you want to change and store them in the folder you created before. Examples for the *.ini files based on your posting above:

    warrior.ini

    userName=warrior
    agilityFactor=1.2
    constitutionFactor=1.1
    intelligenceFactor=1.2
    strengthFactor=1.1
    

    mage.ini

    userName=mage
    agilityFactor=0.8
    constitutionFactor=0.9
    intelligenceFactor=0.8
    strengthFactor=0.9
    

    Finally you can double-click the batch script file to do your changes. The script will create a backup of your original XML file with .bak appended to its file name in the same folder.



  • For the record, the context of the original question was implied to be “within Notepad++” (this is a N++ forum after all).

    When I replied with “It’s a common question, to which the answer is probably not” that was of course within that context.

    If we were going to take it out of the N++ context, the answer is much broader, as @dinkumoil shows.



  • @Alan-Kilborn said in How to increase or decrease the percentage of XML Attribute Values by regex?:

    this is a N++ forum after all

    You are right, of course. But the XSLT solution provided above could also be used with the XML Tools plugin for Notepad++, thus it would stay in the N++ context. But this variant requires the user to enter the appropriate values for the input parameters into a small input box. That’s the reason why I suggested the msxsl.exe solution.



  • This post is deleted!

Log in to reply