Introduction
In addition to Fixed layout API, the Apitron PDF Kit for .NET component provides a Flow layout API which supports css-like styling, and is very similar to HTML in terms of elements structure. The difference between the two is described in the following blog post.
The Flow layout API also supports XML export and import, making it possible to create XML templates for documents or PDF forms and later use them as a base, adding the necessary data or filling the PDF fields for example.
In this article we'll show how to work with XML templates and produce PDF documents using Flow layout API.
In this article we'll show how to work with XML templates and produce PDF documents using Flow layout API.
Creating the base template
Usually, we start with the template by creating it from code, so it’s the code first approach. Of course, it’s possible to create the XML template from scratch, but starting from code is a bit more convenient and speeds up the initial development.
privatestaticvoid CreateTemplate()
{
// create resource manager and register image resource
ResourceManager resourceManager = newResourceManager();
resourceManager.RegisterResource(newImage("logo", "../../images/logo.png", true));
// create document object and register styles
FlowDocument doc = newFlowDocument()
{
Margin = newThickness(30, 20, 30, 20)
};
{
Margin = newThickness(30, 20, 30, 20)
};
// style for image logo
doc.StyleManager.RegisterStyle(".logo", newStyle()
{
Margin = newThickness(0, 0, 10, 10)
});
{
Margin = newThickness(0, 0, 10, 10)
});
// style for note below the header
doc.StyleManager.RegisterStyle(".headerNote", newStyle()
{
Display = Display.InlineBlock,
Align = Align.Justify
});
// style for header
doc.StyleManager.RegisterStyle(".header",
newStyle()
{
Font = newFont(StandardFonts.HelveticaBold, 18),
Display = Display.InlineBlock,
Align = Align.Right,
VerticalAlign = VerticalAlign.Bottom,
Margin = newThickness(0, 0, 0, 10)
});
// style for unordered list
doc.StyleManager.RegisterStyle(".ul", newStyle()
{
ListStyle = ListStyle.Unordered,
ListMarker = ListMarker.Circle,
ListMarkerPadding = newThickness(0, 0, 10, 0),
Margin = newThickness(0, 20, 0, 0)
});
//style for list items
doc.StyleManager.RegisterStyle(".ul > *", newStyle()
{
ListStyle = ListStyle.ListItem,
Margin = newThickness(0, 10, 0, 10)
});
doc.Add(newImage("logo") {Class = "logo"});
doc.Add(newTextBlock("Sample Interview Questions for Candidates")
{
Class = "header"
});
{
Class = "header"
});
doc.Add(newBr());
doc.Add(newTextBlock(
"To help facilitate the interview process the Human Resources Department " +
"has compiled a list of questions that might be used during the phone " +
"and/or on-campus interviews. " +
"Some of the questions deal with the same content, " +
"but are phrased differently while other questions may not pertain " +
"to a specific discipline; however all of the questions" +
" are unbiased and appropriate to ask. We hope you'll find " +
"this helpful.") {Class = "headerNote"});
// add questions list
Section list = newSection() {Class = "ul"};
list.Add(newTextBlock("What do you consider to be one of your greatest
achievements? Why?"));
achievements? Why?"));
list.Add(newTextBlock("What's the latest technology innovation you're aware of?"));
list.Add(newTextBlock("What motivates you to do your best?"));
list.Add(newTextBlock("Why did you choose to apply to this position?"));
list.Add(newTextBlock("What do you consider to be your particular strength(s)?"));
list.Add(newTextBlock("What areas would you like to improve during the next two
years?"));
years?"));
list.Add(newTextBlock("Why are you interested in working in the COMPANY?"));
list.Add(newTextBlock("What do you consider to be your particular weakness(es)?"));
list.Add(newTextBlock("What is the most exciting thing you've been working on
recently?"));
recently?"));
list.Add(newTextBlock("Do you like to be a part of the team or prefer to work
separately?"));
separately?"));
list.Add(newTextBlock("Are you able to work remotely?"));
list.Add(newTextBlock("Why should we hire you?"));
list.Add(newTextBlock("Where do you see yourself in a two years?"));
list.Add(newTextBlock("Why are you leaving your current job?"));
list.Add(newTextBlock("What type of work environment do you prefer?"));
doc.Add(list);
// export as PDF
using (Stream stream = File.Create("out.pdf"))
{
doc.Write(stream, resourceManager);
}
// create XML template
using (Stream stream = File.Create("template.xml"))
{
doc.SaveToXml(stream, resourceManager);
}
}
As you can see from the code sample above, we create a very simple questionnaire for an imaginable HR department. First come the company logo and header, then additional note, and lastly a list of questions. When the document is filled up, we create a PDF for previewing and corresponding XML file for later use.
The generated document looks as follows:
![]() |
Pic. 1 Created PDF document |
The resulting XML template
<?xmlversion="1.0"encoding="utf-8"?>
<FlowDocumentxmlns="Apitron.PDF.Kit.FlowLayout.v1">
<Resources>
<ImageresourceId="logo"fileName="../../images/logo.png" />
</Resources>
<Styles>
<Styleselector="flowdocument">
<Colorvalue="Black" />
</Style>
<Styleselector="grid">
<InnerBorderthickness="1" />
<InnerBorderColorvalue="Black" />
</Style>
<Styleselector=".logo">
<Marginvalue="0,0,10,10" />
</Style>
<Styleselector=".headerNote">
<Alignvalue="Justify" />
<Displayvalue="InlineBlock" />
</Style>
<Styleselector=".header">
<Alignvalue="Right" />
<Displayvalue="InlineBlock" />
<FontresourceId="Helvetica-Bold"size="18" />
<Marginvalue="0,0,0,10" />
<VerticalAlignvalue="Bottom" />
</Style>
<Styleselector=".ul">
<ListMarkervalue="Circle" />
<ListMarkerPaddingvalue="0,0,10,0" />
<ListStylevalue="Unordered" />
<Marginvalue="0,20,0,0" />
</Style>
<Styleselector=".ul > *">
<ListStylevalue="ListItem" />
<Marginvalue="0,10,0,10" />
</Style>
</Styles>
<Elements>
<Image>
<Properties>
<Classvalue="logo" />
<ResourceIdvalue="logo" />
</Properties>
</Image>
<TextBlock>
<Properties>
<Classvalue="header" />
<Textvalue="Sample Interview Questions for Candidates" />
</Properties>
</TextBlock>
<Br />
<TextBlock>
<Properties>
<Classvalue="headerNote" />
<Textvalue="To help facilitate the interview process the Human Resources Department has compiled a list of questions that might be used during the phone and/or on-campus interviews. Some of the questions deal with the same content, but are phrased differently while other questions may not pertain to a specific discipline; however all of the questions are unbiased and appropriate to ask.
We hope you'll find this helpful." />
</Properties>
</TextBlock>
<Section>
<Elements>
<TextBlock>
<Properties>
<Textvalue="What do you consider to be one of your greatest
achievements? Why?" />
</Properties>
</TextBlock>
...questions
<TextBlock>
<Properties>
<Textvalue="What type of work environment do you prefer?" />
</Properties>
</TextBlock>
</Elements>
<Properties>
<Classvalue="ul" />
</Properties>
</Section>
</Elements>
<Properties>
<Marginvalue="30,20,30,20" />
</Properties>
</FlowDocument>
You see that the resulting XML contains styles and values for elements’ properties as well as the path to the image resource registered in document’s resource manager. One of the benefits of having the XML template is the ability to alter documents without recompiling the app. See the next section to learn how to do it.
Changing template
Let’s design our app to accept XML templates as command line argument; in order to do it we’ll implement the entry point of the program as follows:
staticvoid Main(string[] args)
{
if (args == null || args.Length==0)
{
CreateTemplate();
}
else
{
LoadTemplate(args[0]);
}
}
and add the template loading part:
privatestaticvoid LoadTemplate(string templatePath)
{
using (Stream stream = File.OpenRead(templatePath),
outputStream = File.Create("fromTemplate.pdf"))
{
ResourceManager resourceManager = newResourceManager();
FlowDocument doc = FlowDocument.LoadFromXml(stream, resourceManager );
doc.Write(outputStream, resourceManager);
}
}
After that, let’s add new content to the xml template we have. Insert the following piece of XML that creates new textblock in the Elements collection of the Section element:
<TextBlock>
<Properties>
<Colorvalue="Red" />
<Textvalue="Do you have any questions for us?" />
</Properties>
</TextBlock>
It adds new question and makes it drawn in red color. Execute the program with command line parameter “template.xml” and new PDF file will be created for you.
The complete example can be found in our GitHub repository (link).
Resulting PDF document generated from xml template looks as follows:
![]() |
Pic. 2 Modified PDF file created from XML template |
Conclusion
Apitron PDF Kit for .NETcomponent is a reliable PDF library that can be used to process PDF documents of any origin and manipulate their content in any desired way. Its easy to learn and well-structured API speeds up the development process and helps to achieve the desired results saving development time for other tasks.