How to load .txt file into separate .html files? c++ - html

I need to read an HTML file and then separate specific parts of it into individuals HTML files.
For example:
<html lang="en">
<head></head>
<body>
<ul>something 123</ul>
<p>something else 123</p>
<p>blabla</p>
<table>example</table>
</body>
</html>
Everything between <ul> and </ul> should be saved in another HTML file, same with everything between <p> and </p>.
I need to use <fstream> library, and I do not know how to use vectors, so I need to do this probably without them unless there's a simple solution.
The main problem, for now, is, how to read a file until a string is found?
I mean, for example - string table = "<table>" is found and then the program is saving everything after <table> until it finds string end_table = "</table>".
Thanks for your help.

You can use find to locate the beginning and ending body tag with the following:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
string line = "some line with <body> in it";
string bodytag = "<body>";
if(line.find(bodytag) != string::npos) {
cout << "found" << endl;
}
return 0;
}
Then just read lines in from the file until you find the <body> tag and output them until you find the </body> tag. You might need to modify this if content that needs to be saved appears after the opening body tag or before the closing body tag on the same line. Your input doesn't contain this, so this isn't likely a problem.

Related

Putting C++ string in HTML code to show value on webserver

I've set up a webserver running on ESP8266 thats currently hosting 7 sites. The sites is written in plain HTML in each diffrent tab in the arduino ide. I have installed the library Pagebuilder to help with making everything look nice and run.
Except one thing. I have a button connected to my ESP8266 which by the time being imitates a sensor input. basicly when the button is pressed my integer "x" increments with 1. I also managed to make a string that replicates "x" and increments with the same value.
I also have a problem with Printing the IPadresse of the server, but thats not as important as the other.
My plan then was writing the string "score" (which contains x) into the HTML tab where it should be output. this obviously didnt work.
Things I've tried:
Splitting up the HTML code where I want the string to be printed and using client.println("");
This didnt work because the two libraries does not cooperate and WiFiClient does not find Pagebuilders server. (basicly, the client.println does nothing when I used it with Pagebuilder).
Reconstructing the HTML page as a literal really long string, and adding in the String with x like this: "html"+score+"html" and adding it into where the HTML page const char were. (basicly replacing the variable with the text that were in the variable).
This did neighter work because the argument "PageElement" from Pagebuilder does only expect one string, and errors out because theres an additional string inside the HTML string.
I've tried sending it as a post req. but this did not output the value either.
I have run out of Ideas to try.
//root page
#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiClient.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <WebServer.h>
#endif
#include "PageBuilder.h"
#include "currentGame.h" //tab 1
#if defined(ARDUINO_ARCH_ESP8266)
ESP8266WebServer Server;
ESP8266WebServer server;
#endif
int sensorPin = 2; // button input
int sensorValue = 0;
int x = 0; // the int x
String score=""; //the string x will be in
PageElement CURRENT_GAME_ELEMENT(htmlPage1);
PageBuilder CURRENT_GAME("/current-game", {CURRENT_GAME_ELEMENT}); // this //only showes on href /current-game
void button() {
sensorValue = analogRead(sensorPin); //read the voltage
score="Team 1: "+String((int)x+1); //"make" x a string
if (sensorValue <= 10) { // check if button is pressed
x++; // increment x
Serial.println(x);
Serial.println(score);
delay(100);
}
}
void setup() {
Serial.begin(115200);
pinMode(2, INPUT);
WiFi.softAP("SSID", "PASS");
delay(100);
CURRENT_GAME.insert(Server);
Server.begin();
}
void loop() {
Server.handleClient();
button();
}
// tab 1
const char htmlPage1[] PROGMEM = R"=====(
/*
alot of HTML, basicly the whole website...
..............................................
*/
<div class="jumbotron">
<div align="center">
<h1 class="display-4"> score </h1> // <--- this is where
//I want to print the
//string:
</div>
</div>
)=====";
what I want to do is getting the value of the string score displayed on the website. If I put "score" directly into the HTML, the word score will be displayed, not the value. I want the value displayed.
Edit:
I have figured out how to make the string(score) be printed in the HTML code, thus, I only have to convert the HTML code string back to a char. explanation is in comment below.
Edit 2: (-------------------------solution-------------------------)
Many thanks for the help I've gotten and sorry for being so ignorant, its just so hard being so close and that thing doesnt work. but anyways, What I did was following Pagebuilders example, and making another element to print in current game..
String test(PageArgument& args) {
return score;
}
const char html[] = "<div class=\"jumbotron\"><div align=\"center\"><h1 class=\"display-4\">{{NAME}}</h1></div></div>";
PageElement FRAMEWORK_PAGE_ELEMENT(htmlPage0);
PageBuilder FRAMEWORK_PAGE("/", {FRAMEWORK_PAGE_ELEMENT});
PageElement body_elem(html, { {"NAME", test} });
PageElement CURRENT_GAME_ELEMENT(htmlPage1);
PageBuilder CURRENT_GAME("/current-game", { CURRENT_GAME_ELEMENT, body_elem});
suprisingly easy when I first understood it.. Thanks again.
You could try building your string first, then converting it to a const char
like this: const char * c = str.c_str();
if you can't use a pointer you could try this:
string s = "yourHTML" + score + "moreHTML";
int n = s.length();
char char_array[n + 1];
strcpy(char_array, s.c_str());
additionally you could try the stringstream standard library
This sort of thing is often done using magic tags in your markup that are detected by the server code before it serves the HTML and filled in by executing some sort of callback or filling in a variable, or whatever.
So with this in mind and hoping for the best, I nipped over to: PageBuilder on github and looked to see if there was something similar here. Good news! In one of the examples:
const char html[] = "hello <b>{{NAME}}</b>, <br>Good {{DAYTIME}}.";
...
PageElement body_elem(html, { {"NAME", AsName}, {"DAYTIME", AsDayTime} });
Where {{NAME}} and {{DAYTIME}} are magic tokens. AsName and AsDayTime are functions to be called when the respective tag is encountered while the page is being served.
EDIT: in response to a request to explain differently, I'm not convinced I can do a better job of explaining the code than the example on the library's own github page, so I'll try a wordy description instead:
When you want to serve a webpage to a client, the code needs to know what you want to serve. In the simplest case, it's a static page: the same every time. You can just write the HTML, stick it in a string an be done.
whole_page = "<html>My fixed content</html>";
webserver.serve(whole_page);
But you want some dynamic element(s). As noted, you can do it in a few ways, such as serving some static HTML, then the dynamic bit, then some more static HTML. It seems you've not had much luck like this, and it's rather clunky anyway.
Or you can pre-build a new string out of the three bits and serve that in one chunk, but that's also pretty clunky.
(Aside: taking big strings and adding them together is likely to be slow and memory intensive, two things you really don't want on a little CPU like the ESP8266).
So instead, you allow 'magic' markers in the HTML, using a marker in place of the dynamic content, and serve that instead.
whole_page = "<html>My dynamic content. Value is {{my_value}}</html>";
webserver.serve(whole_page, ...);
The clever bit is that as the page is being served, the webserver is watching the text go by, and when it sees a magic tag, it stops and asks you to fill in the blank, then carries on as before.
Obviously, there is some processing overhead with watching for tags, and some programming overhead with telling it what tags to watch for and how to ask you for the data it needs.
I got advice from a friend who told me I should make a unique argument where I wanted the string(x) and then using some syntax to replace it. I also took inspiration from you Jelle..
what I did was make a unique argument "VAR_CURRENT_SCORE" put that into the HTML where I want the score output, then convert htmlPage1 from a char to a string, use string.replace() and replace "VAR_CURRENT_SCORE" with the string(x) score. this workes as I can see in the serial monitor output.
This is what I did:
//root page
String HTMLstring(htmlstringPage);
delay(100);
HTMLstring.replace("VAR_CURRENT_SCORE", score);
delay(50);
Serial.println("string:");
Serial.println(HTMLstring);
//tab 1 char htmlstringPage[] PROGMEM = R"=====(
<div class="jumbotron">
<div align="center">
<h1 class="display-4">VAR_CURRENT_SCORE</h1>
</div>
</div>
)=====";
However, I still have a small problem left which is converting the string back to char to post it to the website.
To convert the string back:
request->send_P(200, "text/html", HTMLstring.c_str());

How to read a specific HTML part in a C++ program?

I am a very beginner. I have a C++ program in CLI, with a HTML/XML input file thanks to a ifstream file("C:/.......").
The main problem is I want to take some text in this file, and put into variable. But the difficulties I meet is that I only want to take some part of the file, for instance in a var1. I want text which is between the HTML tag <name> or the one I choose.
I already tried to put some getline with condition or move cursors but I only have all the text or nothing.
//here some part of the code that i'm sure of
string info(""), line(""), system("");
ifstream file("C:/Users/[...]/file.xml");
if (file.is_open())
{
while (getline(file, line))
{
cout << line << endl;
}
file.close();
}
else
cout << "file is not open" << endl;
Then I call the var with the the text, sorry for English mistakes or code mistakes, and thanks in advance if you could give me some clues.

Adding images in html page using c++ file handling

I have created one html file using ofstream in c++. I have one folder in my system and in that I have 10 jpeg images.
Now I want to add that 10 images to my html page using loop.
I have add one image in my html page.
My question is how to add 10 jpeg images which are in same folder but having different names using one loop?
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream folder;
ofstream myfile;
char buffer[500]={'0'};
folder.open("/home/tanmay/exp");
myfile.open ("MY_FILE.html");
myfile << "<!DOCTYPE html>"<<endl;
sprintf(buffer,"00_FrontView.jpg");
myfile<<"<table align=""center"" border=""2""width=""600"" height=""50"">"
<<"<td><center><a href="<<"\""<<buffer<<"\""<<"target=""_self"">"
<<"<img src="<<"\""<<buffer<<"\""<<"width=""150"" height=""100""/>"
<<"</center></td>"<<endl;
myfile << "</table></body></html>";
myfile.close();
folder.close();
return 0;
}

Using QWebkit to retrieve divs with a specific class

I posted the question below, trying to use the QDomDocument classes. I was advised to use the QWebkit instead, but I'm very confused how to do what I need to do with QWebkit. I've never used it before so I'm rather unsure with it. Could anyone please offer any advice? Thanks!
For the record, the function is using a QByteArray that when translated to text is a standard HTML file.
ORIGINAL QUESTION:
I have several divs in an HTML file with different classes, like this:
<div class='A'>...</div>
<div class='B'>...</div>
<div class='C'>...</div>
I have a Qt (4.7) program where I need to be able to get a certain div out of this based on the class. I need to use QDomDocument in this program. I know from the documentation that that class has a function elementById(), but I can't get that to work with classes, just ids. This isn't a HTML file a made or anything, so I don't have any control over whether it's class or id. Is there a way to do this that I'm missing? Thanks!
.pro
QT += webkitwidgets
main.cpp
#include <QApplication>
#include <QDebug>
#include <QWebView>
#include <QWebFrame>
#include <QWebElement>
int main( int argc, char *argv[] ) {
QApplication a(argc, argv);
QString l_html( "<html><body>"
"<div class='A'>div with class A</div>"
"<div class='B'>div with class B</div>"
"<div class='C'>div with class C</div>"
"<span class='A'>span with class A</span>"
"</body></html>" );
QWebView l_webView; // you can skip the QWebView if you dont want to show any widget
l_webView.page()->mainFrame()->setHtml( l_html );
QWebElement l_root( l_webView.page()->mainFrame()->documentElement() );
QWebElementCollection l_elements( l_root.findAll( ".a" ) );
foreach ( QWebElement l_e, l_elements ) {
// do what you want here
}
return a.exec();
}

Scraped HTML is not written at the beginning of text file

Currently, I'm scraping the HTML code of a page, and writing it to a text file.
My problem is, why must there be empty spaces or empty lines at the beginning? The HTML codes written to the txt file do not seem to start at the beginning of the text file. This means that the '<' is not located at the position 0 of the txt file.
After a few runs, my HTML is always written a few lines down inside the text file.
Can anyone tell me why?
Below is my code. I'm doing it under Visual C++ .
UINT32 LOG(wstring log, UINT32 flag)
{
wfstream file (LOG_FILE, ios_base::app);
file << log;
file.close();
return 1;
}
My problem is, the HTML code copied to my text file is always down a couple of lines, then will find the '<' tag. What I want is, the HTML's first '<' is written at the position 0 of my text file :)
Below is my code. I'm doing it under Visual C++ .
UINT32 LOG(wstring log, UINT32 flag)
{
if(flag == 0)
{
wfstream file (LOG_FILE, ios_base::app);
if (file.is_open())
{
file << log <<endl;
file.close();
wcout << endl << log << endl;
return 0;
}
else wcout << "\nUnable to open LOG file\n";
return 1;
}
My problem is, the HTML code copied to my text file is always down a couple of lines, then will find the '<' tag. What I want is, the HTML's first '<' is written at the position 0 of my text file :)