Retrieve data from XML file and edit it

2

1

Suppose following example:

I have an XML file called plants.xml

<?xml version="1.0" encoding="utf-8"?>
<Plant>
<Zone Left="{PRKNG-7}">
<Data key="Bloodroot">Sanguinaria_canadensis</Data>
<Data key="Columbine">Aquilegia_canadensis</Data>
<Data key="Hepatica">Hepatica_americana</Data>
<Data key="Mayapple">Podophyllum_peltatum</Data>
</Zone>
<Direction Right="{PRKNG-8}">
<Data key="Zone">4</Data>
<Data key="Light">Shade</Data>
<Data key="Depth">Surface</Data>
<Data key="Availability">23262156</Data>
</Direction>
</Plant>

With PowerShell, I want to retrieve the number "23262156" behind "Availibility", add 1 and save the XML again.

I do not want to replace the number (since it is different each time), just add 1, so that it is 23262157.

Next time the number might be 234159 and I want to add 1 again, so it'll be 234160.

To be clear: I don't want to use to "replace" command. Get-Content c:\1.txt | ForEach-Object { $_ -replace "23262156", "23262157" } | Set-Content c:\1.txt I want to use something like "23262156" +1 so the outcome is 23262157. Because next time I run the script there might be another number. If I execute a "replace" command then the outcome will be again 23262157 instead of the number +1.

James

Posted 2018-08-31T18:13:27.240

Reputation: 21

Is availability always at the same line? – Sonamor – 2018-08-31T21:05:46.597

(1) I don’t understand what you mean by “I do not want to replace the number”. You want to write “03262157” to the file, don’t you? To you want to *add* an entry that says <Data key="Availibility">03262157</Data> in addition to the one that says <Data key="Availibility">03262156</Data>? No? You want to replace the one that says <Data key="Availibility">03262156</Data> with one that says <Data key="Availibility">03262157</Data>? Please explain.  (2) Just out of curiosity, do your data really misspell “Availability”? (3) Do you really need to preserve leading zero(es)? … (Cont’d) – Scott – 2018-09-01T22:04:52.917

(Cont’d) …  (4) It is generally recommended that you use an XML parser to parse XML, and not try to approach it with general-purpose text-processing tools. … … … … … … … … … … … … … … … Please do not respond in comments; [edit] your question to make it clearer and more complete.

– Scott – 2018-09-01T22:04:54.910

(1) I explained a little better. No Replace command, but make the sum of the number +1. (2) Type, it should be "Availability". Sorry :) (3) I fact the number can vary, but it was a bad example. There will never be a leading zero. (4) I know, but I can't figure it out. That's why I need your help. – James – 2018-09-02T13:24:49.457

No, Availability is not always on the same line. – James – 2018-09-02T18:50:47.980

Answers

1

Use XSLT:

#transform to HTML report
$xslt=New-Object System.Xml.Xsl.XslCompiledTransform
$xslt.Load("$pwd\transform.xsl")
$xslt.Transform("$pwd\original.xml","$pwd\result.xml") 

With the following stylesheet:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"
            >
<xsl:template match="node()" mode="print">

        <xsl:choose>

            <!-- is it element? -->
            <xsl:when test="name()">
                <br />

                <!-- start tag -->
                <xsl:text>&lt;</xsl:text>
                <xsl:value-of select="name()" />

                <!-- attributes -->
                <xsl:apply-templates select="@*" mode="print" />

                <xsl:choose>

                    <!-- has children -->
                    <xsl:when test="node()">
                        <!-- closing bracket -->
                        <xsl:text>&gt;</xsl:text>

                        <!-- children -->
                        <xsl:apply-templates mode="print" />

                        <!-- end tag -->
                        <xsl:text>&lt;/</xsl:text>
                        <xsl:value-of select="name()" />
                        <xsl:text>&gt;</xsl:text>
                        <br />
                    </xsl:when>

                    <!-- is empty -->
                    <xsl:otherwise>

                        <!-- closing bracket -->
                      <xsl:text>/&gt;</xsl:text><br />

                      <br />
                    </xsl:otherwise>

                </xsl:choose>

            </xsl:when>

            <!-- text -->
            <xsl:otherwise>
                <xsl:copy />
            </xsl:otherwise>

        </xsl:choose>

</xsl:template>

<xsl:template match="@*" mode="print">
    <xsl:text> </xsl:text>
    <xsl:value-of select="name()" />
    <xsl:text>=&quot;</xsl:text>
    <xsl:value-of select="." />
    <xsl:text>&quot;</xsl:text>
</xsl:template>


<xsl:template match="text()" mode="print">
    <xsl:choose>

      <xsl:when test="contains(parent::node()/@key, 'Availability')">
        <xsl:value-of select="number(current()) + 1" />
      </xsl:when>

      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="/">
  <xsl:apply-templates mode="print" />
</xsl:template>

</xsl:stylesheet>

Which produces the following output:

http://fiddle.frameless.io/ References

Paul Sweatte

Posted 2018-08-31T18:13:27.240

Reputation: 613