1
00:00:00,340 --> 00:00:03,650
Okay, so our last thing to focus on here is the loading

2
00:00:03,650 --> 00:00:08,540
and iterating of both XML and JSON data.

3
00:00:08,540 --> 00:00:12,330
Now there are some common commands available to us in PowerShell.

4
00:00:12,330 --> 00:00:13,700
We don't have to write everything.

5
00:00:13,700 --> 00:00:16,360
I know that we're talking about writing PowerShell scripts,

6
00:00:16,360 --> 00:00:19,930
but we can use existing cmdlets to help us here.

7
00:00:19,930 --> 00:00:25,210
The first one is ConvertTo‑Xml. This cmdlet creates an XML‑based

8
00:00:25,210 --> 00:00:30,340
representation of one or more .NET objects.

9
00:00:30,340 --> 00:00:33,920
We also, then have ConvertFrom‑Json, which will basically

10
00:00:33,920 --> 00:00:38,160
convert a JSON‑formatted string to a custom object, or we

11
00:00:38,160 --> 00:00:40,640
can pipe that out to a hash table.

12
00:00:40,640 --> 00:00:43,420
We also, then have the ConvertTo‑Json,

13
00:00:43,420 --> 00:00:45,830
which will convert whatever the object is we've

14
00:00:45,830 --> 00:00:50,540
chosen to a JSON‑formatted string.

15
00:00:50,540 --> 00:00:56,940
Now to load XML, the simplest approach is to use the SELECT‑XML command.

16
00:00:56,940 --> 00:01:03,540
It uses an XPath query to search for text in the XML strings and/or documents,

17
00:01:03,540 --> 00:01:08,760
and it requires the path of the XML file and the XPath within the XML

18
00:01:08,760 --> 00:01:12,440
document to be able to search for specific values.

19
00:01:12,440 --> 00:01:17,130
So from a simple perspective, we pass a path, and we choose the XPath.

20
00:01:17,130 --> 00:01:18,470
Now you would need to know this.

21
00:01:18,470 --> 00:01:20,220
So I define two variables.

22
00:01:20,220 --> 00:01:24,130
One is $path which goes to my Countries.xml, and then my

23
00:01:24,130 --> 00:01:26,900
$xpath, if I was to look at my XML definition,

24
00:01:26,900 --> 00:01:32,180
and I clearly have Countries as an XML option, Country, and then Name.

25
00:01:32,180 --> 00:01:34,040
So that's my $xpath.

26
00:01:34,040 --> 00:01:36,920
If I want to retrieve those values and load it,

27
00:01:36,920 --> 00:01:42,610
I simply say Select‑Xml, pass in the ‑Path, which will be the file, and the

28
00:01:42,610 --> 00:01:47,260
‑Xpath, which is the place where the data is in the XML document I wish to

29
00:01:47,260 --> 00:01:53,340
retrieve. Now if I wanted to iterate and retrieve XML data, so let's go

30
00:01:53,340 --> 00:01:58,480
back to kind of the same idea, I've got some XPath information here and a

31
00:01:58,480 --> 00:02:03,500
path. So my $path will be Countries‑with‑Attributes, which has a list of

32
00:02:03,500 --> 00:02:07,320
countries plus some of the values, and then $xpath, which will be

33
00:02:07,320 --> 00:02:08,800
/Countries/Country.

34
00:02:08,800 --> 00:02:10,560
So if you think of this logically,

35
00:02:10,560 --> 00:02:14,430
my XML document must have countries and then each

36
00:02:14,430 --> 00:02:17,580
country listed. To retrieve that,

37
00:02:17,580 --> 00:02:21,860
I'm going to say load the XML data first into an XML variable.

38
00:02:21,860 --> 00:02:24,950
So Select‑Xml ‑Path is the $path.

39
00:02:24,950 --> 00:02:29,480
‑Xpath is the $xpath I wish to reiterate. And then we can loop, and

40
00:02:29,480 --> 00:02:33,310
it's as simple as saying here's my XML object, pipe it into

41
00:02:33,310 --> 00:02:39,810
ForEach‑Object, and then say $_.Node.name, and that will iterate

42
00:02:39,810 --> 00:02:44,610
just the named values that we're iterating. Now we could also do

43
00:02:44,610 --> 00:02:46,700
this differently and say, well, actually,

44
00:02:46,700 --> 00:02:51,960
what I'd like to do is just load it as a big object and not have to

45
00:02:51,960 --> 00:02:55,950
use the XPath. So I can define a variable as xml.

46
00:02:55,950 --> 00:02:59,440
You'll see [xml] and the variable.

47
00:02:59,440 --> 00:03:02,940
Then use an out‑of‑the‑box cmdlet called Get‑Content

48
00:03:02,940 --> 00:03:05,310
and pass the path of the XML file.

49
00:03:05,310 --> 00:03:06,700
At that point,

50
00:03:06,700 --> 00:03:11,410
I have to know the path to get the value. So you would have to look at it

51
00:03:11,410 --> 00:03:19,820
and say, okay, $xml.Countries.Country.Name.Population. So what are the

52
00:03:19,820 --> 00:03:23,000
steps for iterating through XML data? Well,

53
00:03:23,000 --> 00:03:27,420
the first one is to read the file and cast it directly to an XML object.

54
00:03:27,420 --> 00:03:29,240
That's the first step.

55
00:03:29,240 --> 00:03:32,690
Second one is then to iterate through the XML data,

56
00:03:32,690 --> 00:03:37,640
and then the third is to return the results of that iteration.

57
00:03:37,640 --> 00:03:38,970
So, as an example,

58
00:03:38,970 --> 00:03:44,250
let's imagine that we have an XML file with countries with some checked values.

59
00:03:44,250 --> 00:03:48,780
If I wanted to retrieve and iterate and write values out,

60
00:03:48,780 --> 00:03:52,600
then we could create something like this. So you can see, we're creating an

61
00:03:52,600 --> 00:03:56,740
XML object. We're getting the content from that path.

62
00:03:56,740 --> 00:04:00,560
What I'm then doing is instead of me trying to iterate through all of it,

63
00:04:00,560 --> 00:04:07,420
I'm going to say $xml, which is my now full XML file, .Countries.Country.

64
00:04:07,420 --> 00:04:12,280
So I want to iterate every country. So once I've got that as an object,

65
00:04:12,280 --> 00:04:14,800
I'm going to pipe that into a where object,

66
00:04:14,800 --> 00:04:17,860
which is where I'm looking for a field property in that

67
00:04:17,860 --> 00:04:22,440
XML file, which is called Validated, and it's equal to True.

68
00:04:22,440 --> 00:04:26,840
Once I've got that, I basically have an array of values,

69
00:04:26,840 --> 00:04:30,740
which means that I can then foreach loop at that point.

70
00:04:30,740 --> 00:04:33,340
So I'm going to say, ForEach‑Object,

71
00:04:33,340 --> 00:04:38,240
go and create me a PSCustomObject, and get me the values out.

72
00:04:38,240 --> 00:04:42,440
So, this allows me to retrieve data from XML,

73
00:04:42,440 --> 00:04:46,550
identify without having to use an XPath, and then

74
00:04:46,550 --> 00:04:51,040
populate that into a PSCustomObject.

75
00:04:51,040 --> 00:04:54,900
Now working with JSON is a little bit more popular as JSON is

76
00:04:54,900 --> 00:04:57,830
very lightweight. Now working with JSON,

77
00:04:57,830 --> 00:05:00,940
we have the ability to import the JSON.

78
00:05:00,940 --> 00:05:04,380
We can also export JSON, and we can, of course,

79
00:05:04,380 --> 00:05:08,710
test JSON, so very much like working with XML. Now to

80
00:05:08,710 --> 00:05:12,180
import a JSON file, we simply have a path, so you can see

81
00:05:12,180 --> 00:05:14,140
I've got a list of countries again,

82
00:05:14,140 --> 00:05:17,890
but they're in a JSON format. And we use the same thing where we say

83
00:05:17,890 --> 00:05:22,930
Get‑Content into a variable, but you're using one of the predetermined and

84
00:05:22,930 --> 00:05:29,690
created cmdlets called ConvertFrom‑JSON. That cmdlet will take the JSON and be

85
00:05:29,690 --> 00:05:33,240
able to load it as the format that's required.

86
00:05:33,240 --> 00:05:38,300
If I wanted to export it, whatever the JSON or the variable contained,

87
00:05:38,300 --> 00:05:42,430
I can use ConvertTo‑JSON, and then I'm piping that value

88
00:05:42,430 --> 00:05:45,740
to an Out‑File in a specific path.

89
00:05:45,740 --> 00:05:47,750
If I wanted to test it,

90
00:05:47,750 --> 00:05:53,010
I could get the content to a path, so my Countries.json, and then I can

91
00:05:53,010 --> 00:06:00,010
pipe that into Test‑JSON that will validate that that structure is actual

92
00:06:00,010 --> 00:06:04,120
JSON. And you need to remember, that's quite important to do because too

93
00:06:04,120 --> 00:06:06,950
often people are moving JSON data around.

94
00:06:06,950 --> 00:06:11,890
It contains characters that doesn't quite work, and so it fails in execution.

95
00:06:11,890 --> 00:06:17,290
So you should always test your JSON. Now if I want to iterate and

96
00:06:17,290 --> 00:06:21,500
retrieve JSON, so we have our variable very much like XML, so we have a

97
00:06:21,500 --> 00:06:25,640
variable called $path to a JSON file, you can see what I'm doing here is

98
00:06:25,640 --> 00:06:30,810
go $json, get the content to the path. use the ConvertFrom‑JSON, and

99
00:06:30,810 --> 00:06:35,410
then it works like XML. I can say $json.Countries, and it will iterate

100
00:06:35,410 --> 00:06:36,940
the countries for me.

101
00:06:36,940 --> 00:06:41,260
I could also use a standard Foreach loop by just saying for every

102
00:06:41,260 --> 00:06:44,340
item in the JSON, and then I have to kind of know the path a

103
00:06:44,340 --> 00:06:47,880
little bit, so $item.Countries.Country, and then select the

104
00:06:47,880 --> 00:06:50,040
object that I want to display.

105
00:06:50,040 --> 00:06:54,400
And then, of course, I can use a Foreach with what's called an expand.

106
00:06:54,400 --> 00:06:59,200
Now ‑ExpandProperty will take a specific value and allow

107
00:06:59,200 --> 00:07:01,940
me to kind of pop that value open,

108
00:07:01,940 --> 00:07:06,240
allowing me access to the values that reside inside that.

109
00:07:06,240 --> 00:07:07,210
So if you think about it,

110
00:07:07,210 --> 00:07:11,230
if I do $item.Countries, that will list me all of the countries,

111
00:07:11,230 --> 00:07:15,040
but not the properties that reside inside the country.

112
00:07:15,040 --> 00:07:19,960
So if I do Select‑Object ‑ExpandProperty Country, and then pipe it out,

113
00:07:19,960 --> 00:07:24,940
that means I now get access to Name and Population.

114
00:07:24,940 --> 00:07:27,540
Now we also have the ability in PowerShell to

115
00:07:27,540 --> 00:07:31,570
retrieve JSON from other RESTful APIs.

116
00:07:31,570 --> 00:07:38,640
So there's a public set of APIs at swapi.dev, and one of them is called people.

117
00:07:38,640 --> 00:07:39,680
And to do this,

118
00:07:39,680 --> 00:07:42,570
I'm going to load a variable called $json, use what's called

119
00:07:42,570 --> 00:07:47,540
Invoke‑RestMethod, pass in the URI or the URL to that one.

120
00:07:47,540 --> 00:07:50,030
This will then return a set of results,

121
00:07:50,030 --> 00:07:54,290
which I can then use a standard for each. Now notice the

122
00:07:54,290 --> 00:07:56,970
difference here. When you're using a RESTful API,

123
00:07:56,970 --> 00:08:00,040
there's always a results object that comes back.

124
00:08:00,040 --> 00:08:02,840
So I'm going to say Foreach item, so the item in the

125
00:08:02,840 --> 00:08:07,420
$json.results. And then because it's JSON,

126
00:08:07,420 --> 00:08:14,000
I get the object of $item and then pass it to a selector to be able to say Name, Height, and Gender.

