I want to update a PowerPoint template using Java and Aspose library:
For Example:
I have key and value in ppt as
firstname:${firstname}
lastname:${lastname}
I have an XML file which contains below data:
<firstname> Arjun </firstname>
<lastname> Rathore</lastname>
I want to dynamically update the ppt firstname with Arjun and lastname with Rathore.
i have tried below code to replace text in ppt templae using Aspose but replacement is not happening as per expectation.
String path="C:\\workspace\\src\\main\\resources\\testdata\\";
Presentation presentation = new Presentation(path+"sample.pptx");
presentation.joinPortionsWithSameFormatting();
String strToReplace = "Done";
ITextFrame[] tb = SlideUtil.getAllTextFrames(presentation, true);
String strToFind = "sample";
System.out.println("Before for");
for (int i = 0; i < tb.length; i++)
{
for (IParagraph ipParagraph : tb[i].getParagraphs())
{
ipParagraph.getText().replace(strToFind,strToReplace);
System.out.println("replaced");
for (IPortion iPortion : ipParagraph.getPortions())
{
if (iPortion.getText().toLowerCase().contains(strToFind.toLowerCase()))
{
iPortion.setText(iPortion.getText().toLowerCase().replace(strToFind,strToReplace));
System.out.println("replaced");
}
}
}
}
presentation.save(path+"Output.pptx",SaveFormat.Pptx);
Please find below attachment for reference:
1)input_ppt_template
input_ppt_template screenshot
2)input_xml_data
input_xml_data screenshot
3)expected_output_ppt
expected_output_ppt screenshot
I have observed the images shared by you and based on that created a sample application that shall do the replacement of the text based on data read from XML file. Please try using following sample example for your kind reference.
public static void TestTextReplacment()
{
String path="C:\\Aspose Data\\XMLdata\\";
Presentation presentation = new Presentation(path+"TextToReplace.pptx");
List<Data>ListData=LoadXML();
String[] strToFindArray= {"{{clientName}}","{{contactNumber}}","{{contactAddress}}"};
presentation.joinPortionsWithSameFormatting();
String strToReplace = "Done";
ITextFrame[] tb = SlideUtil.getAllTextFrames(presentation, true);
System.out.println("Before for");
for(int x=0;x<strToFindArray.length;x++)
{
String strToFind=strToFindArray[x];
for (int i = 0; i < tb.length; i++)
{
for (IParagraph ipParagraph : tb[i].getParagraphs())
{
//ipParagraph.getText().replace(strToFind,strToReplace);
//System.out.println("replaced");
for (IPortion iPortion : ipParagraph.getPortions())
{
if (iPortion.getText().toLowerCase().contains(strToFind.toLowerCase()))
{
System.out.println(iPortion.getText());
//iPortion.setText(iPortion.getText().toLowerCase().replace(strToFind,strToReplace));
if(x==0)
{
iPortion.setText(iPortion.getText().toLowerCase().replace(strToFind.toLowerCase(),ListData.get(0).clientName));
}
else if(x==1)
{
iPortion.setText(iPortion.getText().toLowerCase().replace(strToFind.toLowerCase(),ListData.get(0).clientNumber));
}
else
{
iPortion.setText(iPortion.getText().toLowerCase().replace(strToFind.toLowerCase(),ListData.get(0).clientAddress));
}
System.out.println("After: "+ iPortion.getText());
System.out.println("replaced");
}
}
}
}
}
presentation.save(path+"Output.pptx",SaveFormat.Pptx);
}
public static List<Data> LoadXML()
{
File file = new File("C:\\Aspose Data\\XMLdata\\TestData.xml");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder documentBuilder;
Document document=null;
try
{
documentBuilder = documentBuilderFactory.newDocumentBuilder();
document = documentBuilder.parse(file);
}
catch (Exception e)
{
e.printStackTrace();
}
NodeList nList = document.getElementsByTagName("data");
List<Data> dataList=new ArrayList<Data>();
System.out.println("----------------------------");
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE)
{
Data data=new Data();
Element eElement = (Element) nNode;
System.out.println(eElement.getNodeName());
data.clientName=eElement.getElementsByTagName("clientName").item(0).getChildNodes().item(0).getNodeValue();
data.clientNumber=eElement.getElementsByTagName("clientNumber").item(0).getChildNodes().item(0).getNodeValue();
data.clientAddress=eElement.getElementsByTagName("clientAddress").item(0).getChildNodes().item(0).getNodeValue();
dataList.add(data);
}
}
return dataList;
}
I have created a Data class to load data from XML.
public class Data {
public String clientName;
public String clientNumber;
public String clientAddress;
Data()
{
clientName="";
clientNumber="";
clientAddress="";
}
public String getclientName(){return clientName;}
public String getclientNumber(){return clientNumber;}
public String getclientAddress(){return clientAddress;}
public void setclientName(String ClientName){clientName=ClientName;}
public void setclientNumber(String ClientNumber){clientNumber=ClientNumber;}
public void setclientAddress(String ClientAddress ){clientAddress=ClientAddress;}
}
Attached here, please source presentation, source XML and generated output presentation for your reference. I hope the shared example will be helpful to you now.
I am working as Support developer/ Evangelist at Aspose.
Related
in my case its not full xml instead of that i want to parse the part of one xml tag to be parsed.
<FILTERABLE>
<FILTER_ELEMENT ALIAS_NAME="roomnumber" JOINER="AND" LPAREN="false" OPERATOR="BEGINS" RPAREN="false" SEQNUM="1" VALUE="1001"/>
</FILTERABLE>
Please help to convert the code into java object.
ByteArrayInputStream bis = new ByteArrayInputStream(filterStrValue.getBytes("UTF-8"));
Document document = EntityCollectionXMLUtil.DomfromXML(new InputSource(bis), false);
Element rootElement = document.getDocumentElement();
rootElement.getElementsByTagName("FILTERABLE")
Need one java object as a pair of hash map contains below
FILTER_ELEMENT ALIAS_NAME = "roomnumber"
JOINER="AND"
LPAREN="false"
OPERATOR="BEGINS"
RPAREN="false"
SEQNUM="1"
VALUE="1001"
dom4j is an open source, Java-based library for parse XML documents. in this answer used dom4j api for parse the xml document. hence, add the dom4j.jar file into your application's classpath.
class of FILTER_ELEMENT
public class Filter_Element {
private String ALIAS_NAME;
private String JOINER;
private Boolean LPAREN;
private String OPERATOR;
private Boolean RPAREN;
private int SEQNUM;
private int VALUE;
public String getALIAS_NAME() {
return ALIAS_NAME;
}
public void setALIAS_NAME(String aLIAS_NAME) {
ALIAS_NAME = aLIAS_NAME;
}
public String getJOINER() {
return JOINER;
}
public void setJOINER(String jOINER) {
JOINER = jOINER;
}
public Boolean getLPAREN() {
return LPAREN;
}
public void setLPAREN(Boolean lPAREN) {
LPAREN = lPAREN;
}
public String getOPERATOR() {
return OPERATOR;
}
public void setOPERATOR(String oPERATOR) {
OPERATOR = oPERATOR;
}
public Boolean getRPAREN() {
return RPAREN;
}
public void setRPAREN(Boolean rPAREN) {
RPAREN = rPAREN;
}
public int getSEQNUM() {
return SEQNUM;
}
public void setSEQNUM(int sEQNUM) {
SEQNUM = sEQNUM;
}
public int getVALUE() {
return VALUE;
}
public void setVALUE(int vALUE) {
VALUE = vALUE;
}
}
attributes values of xml element (FILTER_ELEMENT) set to the filterElement object
try {
File fXmlFile = new File("your_xml_file.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
NodeList nodeList= doc.getElementsByTagName("FILTER_ELEMENT");
Filter_Element filterElement;
for(int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
filterElement = new Filter_Element();
filterElement.setALIAS_NAME(node.getAttributes().getNamedItem("ALIAS_NAME").getNodeValue());
filterElement.setJOINER(node.getAttributes().getNamedItem("JOINER").getNodeValue());
filterElement.setLPAREN(Boolean.valueOf(node.getAttributes().getNamedItem("LPAREN").getNodeValue()));
filterElement.setOPERATOR(node.getAttributes().getNamedItem("OPERATOR").getNodeValue());
filterElement.setRPAREN(Boolean.valueOf(node.getAttributes().getNamedItem("RPAREN").getNodeValue()));
filterElement.setSEQNUM(Integer.valueOf(node.getAttributes().getNamedItem("SEQNUM").getNodeValue()));
filterElement.setVALUE(Integer.valueOf(node.getAttributes().getNamedItem("VALUE").getNodeValue()));
}
} catch (Exception e) {
e.printStackTrace();
}
I'm saving some content from a xml file in a ArrayList, to show in a carousel, so everytime someone enter the website, the xml is downloaded and etc, i don't want that, so i'm saving it in cache using ehcache. But i'm having a problem, in the method to get the Array that is stored, the cache return null, there's nothing there. I'm kinda stuck in this part... maybe i'm getting the cache in a wrong way.
public class xmlCache {
//getting the xml file in a Document
public static Document loadXMLDocument() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
return factory.newDocumentBuilder().parse(new URL("https://www.w3schools.com/xml/cd_catalog.xml").openStream());
}
//putting the xml content in a ArrayList
public static ArrayList<String> listXML(){
ArrayList<String> xmlList = new ArrayList<String>();
try {
Document doc = xmlCache.loadXMLDocument();
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("CD");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
xmlList.add(eElement.getElementsByTagName("TITLE").item(0).getTextContent() + "|" +
eElement.getElementsByTagName("ARTIST").item(0).getTextContent() + "|" +
eElement.getElementsByTagName("COUNTRY").item(0).getTextContent() + "|" +
eElement.getElementsByTagName("COMPANY").item(0).getTextContent() + "|" +
eElement.getElementsByTagName("YEAR").item(0).getTextContent());
}
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return xmlList;
}
//putting the ArrayList in cache
public static void cachingXML () {
ArrayList<String> xmlList = xmlCache.listXML();
CacheManager cacheManager = newCacheManagerBuilder().withCache("basicCache", newCacheConfigurationBuilder(Long.class, ArrayList.class, heap(300).offheap(5, MB)))
.build(true);
Cache<Long, ArrayList> basicCache = cacheManager.getCache("basicCache", Long.class, ArrayList.class);
basicCache.put(1L, xmlList);
ArrayList<String> teste = new ArrayList<>();
// if i do that here, is ok, the return is ok
teste = basicCache.get(1L);
System.out.println(teste.size());
}
//accessing the ArrayList stored
public static ArrayList<String> getTicker() {
ArrayList<String> ticker = new ArrayList<>();
try(CacheManager cacheManager = newCacheManagerBuilder().withCache("basicCache", newCacheConfigurationBuilder(Long.class, ArrayList.class, heap(500).offheap(3, MB)))
.build(true)){
Cache<Long, ArrayList> basicCache = cacheManager.getCache("basicCache", Long.class, ArrayList.class);
//the return is false
System.out.println(basicCache.containsKey(1L));
}catch (Throwable e) {
e.printStackTrace();
}
return ticker;
}
public static void main(String[] args) throws MalformedURLException, SAXException, IOException, ParserConfigurationException {
//this one is ok
xmlCache.cachingXML();
//this one is not
xmlCache.getTicker();
}
}
I know I can hardcode it (parse xml, extract), but is there a way to feed (attribute value + nodevalue) like it is done with Feed4TestNG (it currently support only csv, and excel files)?
I am new to Java, and any expert insight would be helpful. Thanks!
The body of a #Parameters is not limited to data only, you are able to use any java code you like in this method, including throwing exceptions:
#Parameters
public static Collection<Object[]> data() throws IOException {
List<Object[]> data = new ArrayList<>();
// replace getClass() with <nameofclass>.class
try(InputStream in = this.getClass().getResourceAsStream()) {
//parse body here
data.add(new Object[]{attribute, value});
}
return data;
}
Depending on what XML framework you use, you need to parse your XML nodes, and put it in the list, that you are going to return.
So this is what I end up doing here:
Please submit your correction if you think I can improve my code.
.
#RunWith(Parameterized.class)
public class DataDrivenTests {
private String c;
private String b;
private static Collection<Object[]> a;
#Parameters
public static Collection<Object[]> xmlData() throws IOException{
File file = new File("xmlfile.xml");
InputStream xml1 = new FileInputStream(file);
return new xmlData(xml1).getData();
}
public DataDrivenTests(String c, String b) {
super();
this.c = c;
this.b = b;
}
#Test
public void shouldCalculateATimesB() {
boolean assertion = false;
if(c.equals(Parser.parse("Parse this string to Attribute and Value"))){
assertion = true;
}
assertTrue(assertion);
}
}
xmlData.java
public class xmlData{
private transient Collection<Object[]> data = null;
public xmlData(final InputStream xml)throws IOException{
this.data = loadFromXml(xml);
}
public Collection<Object[]> getData(){
return data;
}
private Collection<Object[]> loadFromXml(final InputStream xml)
throws IOException {
List <Object[]> ism_code_map = new ArrayList<Object[]>();
try{
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
DocumentBuilder dBuilder;
dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xml);
doc.getDocumentElement().normalize();
XPath xPath = XPathFactory.newInstance().newXPath();
XPathExpression expression = xPath.compile("//e");
NodeList nodes = (NodeList) expression.evaluate(doc, XPathConstants.NODESET);
for (int i =0; i< nodes.getLength(); i++){
Node nNode = nodes.item(i);
//System.out.println("\nCurrent Element:" + nNode.getTextContent());
if (nNode.getNodeType() == Node.ELEMENT_NODE){
Element eElement = (Element) nNode;
if(eElement.getAttribute("attrname") != null && !eElement.getAttribute("attrname").isEmpty()){
code_map.add(new Object[]{"attrname",eElement.getAttribute("attrname")});
}
}catch(ParserConfigurationException e){
e.printStackTrace();
}catch(SAXException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}catch(XPathExpressionException e){
e.printStackTrace();
}
catch(NullPointerException e){
e.printStackTrace();
}
return code_map;
}
}
i have a class which is returning a string type value and i want to return an String array, so please tell how can i able to do that
i have an xml file like resource.xml
<prompts>
<prompt id="p1">welcome to</prompt>
<prompt id ="p2">stack overflow</prompt>
<prompt id="p3">You entered</prompt>
<prompt id="p4">the correct number</prompt>
<prompts>
i am parsing it using sax parser
public class XmlReaderPrompt {
public List<PromptBean> load(String langMode)
{
String fileName="resource.xml";
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
InputStream prompt_configfile=Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
DocumentBuilder db = null;
List<PromptBean> promptMap = new ArrayList<PromptBean>();
try {
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = null;
try {
doc = db.parse(prompt_configfile);
}
catch (SAXException e) {
e.printStackTrace();
}
NodeList nodeList=doc.getElementsByTagName("prompt");
for(int i=0;i<nodeList.getLength();i++)
{
Node node=nodeList.item(i);
if(node.getNodeType()==Node.ELEMENT_NODE)
{
Element element=(Element)node;
String id = element.getAttribute("id");
String name = element.getAttribute("name");
String prompt=getTextValue(element);
promptMap.add(new PromptBean(id,name,prompt));
}
}
}
catch(Exception io)
{
io.printStackTrace();
}
finally
{
db=null;
dbf=null;
}
return promptMap;
}
private String getTextValue(Element element) {
String textValue=element.getFirstChild().getTextContent().toString();
return textValue;
}
}
and a UserFunction class to return the text from the xml file
public class UserFunction{
List<PromptBean> promptObject = new ArrayList<PromptBean>();
public String getPromptFunction(String promptTag,String langMode )
{
List<PromptBean> promptObject=xrpObject.load(langMode);
for (Iterator<PromptBean> iterator = promptObject.iterator(); iterator.hasNext();){
PromptBean promptBean= (PromptBean)iterator.next();
if(promptBean.getId().equalsIgnoreCase(promptTag)){
return StringEscapeUtils.escapeXml(promptBean.getPrompt());
}
}
return null;
}
The problem is that I have to call the method getPromptFunction of UserFunction class every time I need to get text from the sub element like
String pr1 = UserFunction.getPromptFunction("p1" "resource");
String pr1 = UserFunction.getPromptFunction("p2" "resource");
String pr1 = UserFunction.getPromptFunction("p3" "resource");
and using it in jsp page as <%=pr1%>
So I want to use array like
String[] pr = UserFunction.getPromptFunction('"p1","p2","p3"' "resource")
So how I am able to do that and also tell how to use it in jsp page .
You can do it like this
public String[] getPromptFunction(String promptTag,String langMode )
{
String temp[] = new String[promptObject.size()];
List<PromptBean> promptObject=xrpObject.load(langMode);
int i = 0;
for (Iterator<PromptBean> iterator = promptObject.iterator(); iterator.hasNext();) {
PromptBean promptBean= (PromptBean)iterator.next();
if(promptBean.getId().equalsIgnoreCase(promptTag)){
temp[i] = StringEscapeUtils.escapeXml(promptBean.getPrompt());
}
i++;
}
return temp;
}
I load xml file into DOM model and analyze it.
The code for that is:
public class MyTest {
public static void main(String[] args) {
Document doc = XMLUtils.fileToDom("MyTest.xml");//Loads xml data to DOM
Element rootElement = doc.getDocumentElement();
NodeList nodes = rootElement.getChildNodes();
Node child1 = nodes.item(1);
Node child2 = nodes.item(3);
String str1 = child1.getTextContent();
String str2 = child2.getTextContent();
if(str1 != null){
System.out.println(str1.equals(str2));
}
System.out.println();
System.out.println(str1);
System.out.println(str2);
}
}
MyTest.xml
<tests>
<test name="1">ff1 "</test>
<test name="2">ff1 "</test>
</tests>
Result:
true
ff1 "
ff1 "
Desired result:
false
ff1 "
ff1 "
So I need to distinguish these two cases: when the quote is escaped and is not.
Please help.
Thank you in advance.
P.S. The code for XMLUtils#fileToDom(String filePath), a snippet from XMLUtils class:
static {
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
dFactory.setNamespaceAware(false);
dFactory.setValidating(false);
try {
docNonValidatingBuilder = dFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
}
}
public static DocumentBuilder getNonValidatingBuilder() {
return docNonValidatingBuilder;
}
public static Document fileToDom(String filePath) {
Document doc = getNonValidatingBuilder().newDocument();
File f = new File(filePath);
if(!f.exists())
return doc;
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
DOMResult result = new DOMResult(doc);
StreamSource source = new StreamSource(f);
transformer.transform(source, result);
} catch (Exception e) {
return doc;
}
return doc;
}
I've take a look on source code of apache xerces and propose my solution (but it is monkey patch).
I've wrote simple class
package a;
import java.io.IOException;
import org.apache.xerces.impl.XMLDocumentScannerImpl;
import org.apache.xerces.parsers.NonValidatingConfiguration;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLComponent;
public class MyConfig extends NonValidatingConfiguration {
private MyScanner myScanner;
#Override
#SuppressWarnings("unchecked")
protected void configurePipeline() {
if (myScanner == null) {
myScanner = new MyScanner();
addComponent((XMLComponent) myScanner);
}
super.fProperties.put(DOCUMENT_SCANNER, myScanner);
super.fScanner = myScanner;
super.fScanner.setDocumentHandler(this.fDocumentHandler);
super.fLastComponent = fScanner;
}
private static class MyScanner extends XMLDocumentScannerImpl {
#Override
protected void scanEntityReference() throws IOException, XNIException {
// name
String name = super.fEntityScanner.scanName();
if (name == null) {
reportFatalError("NameRequiredInReference", null);
return;
}
super.fDocumentHandler.characters(new XMLString(("&" + name + ";")
.toCharArray(), 0, name.length() + 2), null);
// end
if (!super.fEntityScanner.skipChar(';')) {
reportFatalError("SemicolonRequiredInReference",
new Object[] { name });
}
fMarkupDepth--;
}
}
}
You need to add only next line to your main method before start parsing
System.setProperty(
"org.apache.xerces.xni.parser.XMLParserConfiguration",
"a.MyConfig");
And you will have expected result:
false
ff1 "
ff1 "
Looks like you can get the TEXT_NODE child and use getNodeValue (assuming it's not NULL):
public static String getRawContent(Node n) {
if (n == null) {
return null;
}
Node n1 = getChild(n, Node.TEXT_NODE);
if (n1 == null) {
return null;
}
return n1.getNodeValue();
}
Grabbed that from:
http://www.java2s.com/Code/Java/XML/Gettherawtextcontentofanodeornullifthereisnotext.htm
There is no way to do this for the internal entities. XML does not support this concept. Internal entities are just a different way to write the same PSVI content into the text, they are not distinctive.