I've created the tool to merge the recipe files with Purebasic. But there is a bug in the XML library I try to show to Fred but I was not able to construct an example without using your recipe files. Can I bundle them in a small package and send to Fred so he can take a look why the XMLExport function does its job wrong?
This is my code so far, but the Data.xml file inside the merged recipe file is not valid because there are some characters missing in the end of the file.
Code: Select all
EnableExplicit
UseZipPacker()
Structure Recipe
file.s
handle.i
Map *files()
content.i
EndStructure
Procedure openRecipe(file.s)
Protected *recipe.Recipe = AllocateStructure(Recipe)
Protected filename.s, *buffer, size.i
If Not *recipe
Debug "Could not allocate memory"
ProcedureReturn #False
EndIf
With *recipe
\handle = OpenPack(#PB_Any, file, #PB_PackerPlugin_Zip)
\file = file
If Not \handle
Debug "Could not open zip"
Goto error
EndIf
If Not ExaminePack(\handle)
Debug "Could not examine zip"
Goto error
EndIf
While NextPackEntry(\handle)
filename = PackEntryName(\handle)
size = PackEntrySize(\handle, #PB_Packer_UncompressedSize)
If PackEntryType(\handle) = #PB_Packer_File
*buffer = 0
If size > 0
*buffer = AllocateMemory(size)
If Not *buffer
Debug "Could not allocate memory for " + filename
Goto error
EndIf
If size <> UncompressPackMemory(\handle, *buffer, size)
Debug "Could not unpack file: " + filename
Goto error
EndIf
EndIf
Else
*buffer = -1
EndIf
\files(filename) = *buffer
If filename = "Data.xml"
If size = 0 Or Not *buffer
Debug filename + " is empty"
Goto error
EndIf
\content = CatchXML(#PB_Any, *buffer, size)
EndIf
Wend
EndWith
ProcedureReturn *recipe
error:
FreeStructure(*recipe)
If *buffer
FreeMemory(*buffer)
EndIf
ProcedureReturn #False
EndProcedure
Procedure getNodeByTag(xmlNode.i)
EndProcedure
Procedure mergeRecipes(file.s, List *recipes.Recipe())
Protected i.i, j.i, *hixz, *node, name.s, *recipesNode, *recipeNode, *sourceImageNode, *recipeImagesNode, *recipeImageNode
Protected imageCounter.i = 0, oldImage.s, newImage.s
; Neuen ZIP-Container erstellen
Protected *mZip = CreatePack(#PB_Any, file, #PB_PackerPlugin_Zip)
; Create new Data.xml
Protected *mData = CreateXML(#PB_Any, #PB_UTF8)
Protected *mHixz = CreateXMLNode(RootXMLNode(*mData), "hixz")
SetXMLAttribute(*mHixz, "Source", "Merged Cookbook")
SetXMLAttribute(*mHixz, "FileVersion", "1.0")
SetXMLAttribute(*mHixz, "date", FormatDate("%yyyy-%mm-%ss", Date()))
Protected *mCookbooks = CreateXMLNode(*mHixz, "Cookbooks")
Protected *mCookbookChapters = CreateXMLNode(*mHixz, "CookbookChapters")
Protected *mRecipes = CreateXMLNode(*mHixz, "Recipes")
; Create new Manifest.xml
Protected *mManifest = CreateXML(#PB_Any, #PB_UTF8)
Protected *mFdxm = CreateXMLNode(RootXMLNode(*mManifest), "fdxm")
SetXMLAttribute(*mFdxm, "Source", "Merged Cookbook")
SetXMLAttribute(*mFdxm, "FileVersion", "1.0")
SetXMLAttribute(*mFdxm, "date", FormatDate("%yyyy-%mm-%ss", Date()))
Protected *mFiles = CreateXMLNode(*mFdxm, "Files")
Protected *mFile
ForEach *recipes()
With *recipes()
*recipesNode = XMLNodeFromPath(RootXMLNode(\content), "/hixz/Recipes")
If Not *recipesNode
Debug \file + ": <recipes> not found."
Continue
EndIf
For i = 1 To XMLChildCount(*recipesNode)
*recipeNode = ChildXMLNode(*recipesNode, i)
*sourceImageNode = XMLNodeFromPath(*recipeNode, "SourceImage")
If *sourceImageNode
oldImage = GetXMLAttribute(*sourceImageNode, "FileName")
newImage = "image" + imageCounter + "." + GetExtensionPart(oldImage)
imageCounter + 1
If FindMapElement(\files(), "Images/" + oldImage)
\files("Images/" + newImage) = \files("Images/" + oldImage)
DeleteMapElement(\files(), "Images/" + oldImage)
EndIf
SetXMLAttribute(*sourceImageNode, "FileName", newImage)
*mFile = CreateXMLNode(*mFiles, "File")
SetXMLAttribute(*mFile, "FileName", newImage)
SetXMLAttribute(*mFile, "OriginalFileName", GetXMLAttribute(*sourceImageNode, "OriginalFileName"))
AddPackMemory(*mZip, \files("Images/" + newImage), MemorySize(\files("Images/" + newImage)), "Images/" + newImage)
EndIf
*recipeImagesNode = XMLNodeFromPath(*recipeNode, "RecipeImages")
If *recipeImagesNode
For j = 1 To XMLChildCount(*recipeImagesNode)
*recipeImageNode = ChildXMLNode(*recipeImagesNode, j)
oldImage = GetXMLAttribute(*recipeImageNode, "FileName")
newImage = "image" + imageCounter + "." + GetExtensionPart(oldImage)
imageCounter + 1
If FindMapElement(\files(), "Images/" + oldImage)
\files("Images/" + newImage) = \files("Images/" + oldImage)
DeleteMapElement(\files(), "Images/" + oldImage)
EndIf
SetXMLAttribute(*recipeImageNode, "FileName", newImage)
*mFile = CreateXMLNode(*mFiles, "File")
SetXMLAttribute(*mFile, "FileName", newImage)
SetXMLAttribute(*mFile, "OriginalFileName", GetXMLAttribute(*recipeImageNode, "OriginalFileName"))
AddPackMemory(*mZip, \files("Images/" + newImage), MemorySize(\files("Images/" + newImage)), "Images/" + newImage)
Next
EndIf
CopyXMLNode(*recipeNode, *mRecipes)
Next
EndWith
Next
Protected size.i, *buffer
;FormatXML(*mData, #PB_XML_ReduceSpace | #PB_XML_CutSpace | #PB_XML_ReduceNewline | #PB_XML_CutNewline | #PB_XML_LinuxNewline)
size = ExportXMLSize(*mData, #PB_XML_NoDeclaration)
Debug size
*buffer = AllocateMemory(size)
If ExportXML(*mData, *buffer, size, #PB_XML_NoDeclaration)
Debug PeekS(*buffer, size, #PB_UTF8)
AddPackMemory(*mZip, *buffer, size, "Data.xml")
FreeMemory(*buffer)
EndIf
size = ExportXMLSize(*mManifest)
*buffer = AllocateMemory(size)
If ExportXML(*mManifest, *buffer, size)
AddPackMemory(*mZip, *buffer, size, "Manifest.xml")
FreeMemory(*buffer)
EndIf
ClosePack(*mZip)
EndProcedure
NewList *recipes.Recipe()
; This directory should only contain the fdxz files
Define dir.s = "/home/nicolas/tmp/purebasic/Recipes/"
; This is the new merged recipes file
Define target.s = "/home/nicolas/tmp/purebasic/Recipes/merged.zip"
; First read all recipes into Memory
If ExamineDirectory(0, dir, "*.fdxz")
While NextDirectoryEntry(0)
If DirectoryEntryType(0) = #PB_DirectoryEntry_File
If AddElement(*recipes())
*recipes() = openRecipe(dir + DirectoryEntryName(0))
EndIf
EndIf
Wend
EndIf
mergeRecipes(target, *recipes())