Skip to content

Instantly share code, notes, and snippets.

@grahamsz
Forked from gregawoods/amazon.rake
Last active March 31, 2021 13:18
Show Gist options
  • Save grahamsz/828447627259992ef3d4fa6473284e6f to your computer and use it in GitHub Desktop.
Save grahamsz/828447627259992ef3d4fa6473284e6f to your computer and use it in GitHub Desktop.
Recursively download XSD documents for use with Amazon MWS.

Recursively download XSD documents for use with Amazon MWS, builds c# stub objects. I've also added a crude form of filtering that lets you eliminate product categories that aren't useful to you (and reduce the resulting c# code significantly)

This is a port of https://gist.github.com/gregawoods/91152da26231f4c2ef2fd10297f8e0ac to C#, with an added call to the xsd.exe utility to create the cs code and also a fix for the poorly generated code that will fail at runtime.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace AmazonMWSFetch
{
class Program
{
const string AMAZON_URL_ROOT = "https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/";
const string STARTING_DOC = "amzn-envelope.xsd";
const string PROJECT_PATH = "c:\\temp";
const string XSD_DIR = "xsd";
const string NET_XSD_TOOL_PATH = "C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.1A\\bin\\NETFX 4.5.1 Tools\\xsd.exe";
// resulting xsd can be pretty gigantic so suppress any categories you don't need
static string[] CATEGORIES_TO_SUPPRESS = new string[] {
"Arts.xsd",
"AutoAccessory.xsd",
"Baby.xsd",
"Beauty.xsd",
"Books.xsd",
"CameraPhoto.xsd",
"CE.xsd",
//// "ClothingAccessories.xsd",
"Coins.xsd",
"Collectibles.xsd",
"Computers.xsd",
"EducationSupplies.xsd",
"EntertainmentCollectibles.xsd",
"FoodAndBeverages.xsd",
"FoodServiceAndJanSan.xsd",
"Furniture.xsd",
"Gourmet.xsd",
"Health.xsd",
"Home.xsd",
// "HomeImprovement.xsd", //can't suppress this as it defines TemperatureRangeType that's used in the base
"Industrial.xsd",
"Jewelry.xsd",
"LabSupplies.xsd",
"LargeAppliances.xsd",
"Lighting.xsd",
"LightMotor.xsd",
"Luggage.xsd",
"LuxuryBeauty.xsd",
"MechanicalFasteners.xsd",
"Miscellaneous.xsd",
"Motorcycles.xsd",
"Music.xsd",
"MusicalInstruments.xsd",
"Office.xsd",
"Outdoors.xsd",
"PetSupplies.xsd",
"PowerTransmission.xsd",
"ProfessionalHealthCare.xsd",
"RawMaterials.xsd",
"Shoes.xsd",
"Sports.xsd",
"SportsMemorabilia.xsd",
// "SWVG.xsd", // can't suppress this as it's needed in the base
"ThreeDPrinting.xsd",
"TiresAndWheels.xsd",
"Tools.xsd",
"Toys.xsd",
"ToysBaby.xsd",
"Video.xsd",
"WineAndAlcohol.xsd",
"Wireless.xsd",
};
static List<string> resultingDocumentList = new List<string>();
protected static void RecursiveFetch(string document)
{
if (resultingDocumentList.Contains(document))
{
return;
}
string filePath = PROJECT_PATH + Path.DirectorySeparatorChar + XSD_DIR + Path.DirectorySeparatorChar + document;
using (var client = new System.Net.WebClient())
{
client.DownloadFile(AMAZON_URL_ROOT + document, filePath);
resultingDocumentList.Add(document);
foreach (string includeUri in from el in XDocument.Load(filePath).Descendants()
where el.Name.LocalName == "include"
select (string)el.Attribute("schemaLocation"))
RecursiveFetch(includeUri);
}
}
static void Main(string[] args)
{
if (!Directory.Exists(PROJECT_PATH))
{
throw new FileNotFoundException();
}
if (!Directory.Exists(PROJECT_PATH + Path.DirectorySeparatorChar + XSD_DIR))
{
Directory.CreateDirectory(PROJECT_PATH + Path.DirectorySeparatorChar + XSD_DIR);
}
// Fetch all amazon xsds using rough logic from https://gist.github.com/gregawoods/91152da26231f4c2ef2fd10297f8e0ac
RecursiveFetch(STARTING_DOC);
// This slims down the Product.xsd file to no longer refer to categories that we don't need, this keeps code bloat down
if (CATEGORIES_TO_SUPPRESS.Any())
{
// if we're suppressing categories we also need to remove those elements from the ProductData selection
string filePath = PROJECT_PATH + Path.DirectorySeparatorChar + XSD_DIR + Path.DirectorySeparatorChar + "Product.xsd" ;
// Remove the Product choices
var doc = XDocument.Load(filePath);
doc.Descendants().Where(el => el.Name.LocalName == "element").Where(el => el.Attribute("ref") != null)
.Where(el=>CATEGORIES_TO_SUPPRESS.Contains(el.Attribute("ref").Value + ".xsd")).Remove();
// Remove the links to the files
doc.Descendants().Where(el => el.Name.LocalName == "include" && CATEGORIES_TO_SUPPRESS.Contains(el.Attribute("schemaLocation").Value)).Remove();
doc.Save(filePath);
}
// Now build and run the xsd executable to build the class file
string arguments = XSD_DIR + Path.DirectorySeparatorChar + STARTING_DOC + " /c /eld /n:Nester.Services.Amazon.MWS";
var startInfo = new System.Diagnostics.ProcessStartInfo
{
WorkingDirectory = PROJECT_PATH,
WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal,
Arguments = arguments,
FileName = NET_XSD_TOOL_PATH,
RedirectStandardInput = true,
UseShellExecute = false
};
var process = new System.Diagnostics.Process();
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
//Finally we need to fix a stupid issue with the generated c# code, see https://www.fedex.com/en-us/developer/faq.html
string generatedFile = PROJECT_PATH + Path.DirectorySeparatorChar + STARTING_DOC.Replace(".xsd", ".cs");
var generatedCode = File.ReadAllText(generatedFile);
generatedCode = generatedCode.Replace("[][]", "[]");
File.WriteAllText(generatedFile, generatedCode);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment