Mastering JavaScript: Building an XML Parser

Introduction to XML and its Importance

XML, or Extensible Markup Language, is a widely used format for structuring data. It’s designed to be both human-readable and machine-readable, making it a popular choice for data interchange between different systems. Whether you are a web developer, a data analyst, or a system integrator, understanding how to work with XML is crucial. In this tutorial, we will explore how to build an XML parser using JavaScript, which you can utilize in your web applications.

By mastering the art of XML parsing, you will unlock the ability to manipulate structured data, such as configuration files, API responses, or even data from legacy systems. This knowledge will help you enhance your applications by integrating data from various sources seamlessly.

Setting Up Your Development Environment

Before we dive into writing our XML parser, let’s make sure your development environment is ready. You will need a code editor; I recommend Visual Studio Code or WebStorm, as they both offer excellent support for JavaScript development. You can download Visual Studio Code from here or use WebStorm by JetBrains if you prefer a more IDE-like environment.

Once you have your code editor installed, create a new folder for this project. Inside the folder, create an `index.html` file and a `parser.js` file. The `index.html` file will serve as our entry point, while the `parser.js` file will hold our XML parsing logic. This structure sets up a clean and organized project workspace.

Understanding XML Structure

To parse XML effectively, you first need to understand its structure. XML consists of elements, attributes, and values arranged in a tree-like format. Each piece of data is contained within tags, and you can also define attributes that provide additional information about elements. Here’s an example of a simple XML structure:

<book>
    <title>Learn JavaScript</title>
    <author>Daniel Reed</author>
    <year>2023</year>
</book>

In this example, the `` is the root element, while ``, `<author>`, and `<year>` are child elements. To extract information from this XML, we’ll need to navigate through these elements in our JavaScript code.</p> <h2>Parsing XML with JavaScript</h2> <p>JavaScript provides several ways to parse XML documents. In modern browsers, the preferred method is to use the `DOMParser` API. This API allows you to create a DOM (Document Object Model) from a string representation of XML. Let’s see how we can take the example XML data we discussed and parse it.</p> <pre><code>// parser.js function parseXML(xmlString) { const parser = new DOMParser(); const xmlDoc = parser.parseFromString(xmlString, 'text/xml'); // Handle errors const parserError = xmlDoc.getElementsByTagName('parsererror'); if (parserError.length > 0) { console.error('Error parsing XML:', parserError[0].textContent); return null; } return xmlDoc; }</code></pre> <p>In the `parseXML` function, we create a new `DOMParser` instance and use its `parseFromString` method to convert our XML string into a DOM object. We also check for errors during parsing, which is crucial for ensuring that our XML is well-structured.</p> <h2>Extracting Data from Parsed XML</h2> <p>Once we have parsed the XML into a DOM object, we can easily extract data using various DOM methods. For example, we can use `getElementsByTagName` to retrieve elements by their tag name. Let’s extend our parser to extract the book’s title, author, and year from the XML document.</p> <pre><code>// parser.js function extractBookInfo(xmlDoc) { const title = xmlDoc.getElementsByTagName('title')[0].textContent; const author = xmlDoc.getElementsByTagName('author')[0].textContent; const year = xmlDoc.getElementsByTagName('year')[0].textContent; return { title, author, year }; }</code></pre> <p>This `extractBookInfo` function retrieves the text content of each element by tag name. We can now combine this with our parsing function to display the book information on our web page.</p> <h2>Integrating the Parser with HTML</h2> <p>Now that we have our XML parser and data extraction functions, it’s time to integrate them into our HTML file. We’ll add a basic user interface that allows users to input XML string data and see the extracted information displayed on the page.</p> <pre><code><!DOCTYPE html> <html lang='en'> <head> <meta charset='UTF-8'> <meta name='viewport' content='width=device-width, initial-scale=1.0'> <title>XML Parser Example</title> <script src='parser.js' defer></script> </head> <body> <h1>XML Parser</h1> <textarea id='xml-input' rows='10' cols='50'></textarea> <br> <button id='parse-button'>Parse XML</button> <h2>Extracted Information</h2> <pre id='output'></pre> </body> </html></code></pre> <p>In this HTML structure, we have a textarea for users to input their XML data and a button to trigger the parsing action. After the parse operation, we will display the extracted book information in a `</p> <pre>` element for readability.</p> <h2>Handling User Interaction</h2> <p>To make our application interactive, we'll add an event listener to the button. When clicked, the XML string from the textarea will be passed to our parser and displayed on the page. Here’s how you can implement it:</p> <pre><code>// parser.js document.getElementById('parse-button').addEventListener('click', () => { const xmlInput = document.getElementById('xml-input').value; const xmlDoc = parseXML(xmlInput); if (xmlDoc) { const bookInfo = extractBookInfo(xmlDoc); document.getElementById('output').textContent = JSON.stringify(bookInfo, null, 2); } });</code></pre> <p>This code snippet sets up a click event listener on the button. When clicked, it gets the XML input, parses it, and if successful, extracts the book info and displays it in a formatted JSON structure on the web page.</p> <h2>Testing Your XML Parser</h2> <p>With everything set up, it’s time to test our XML parser. Open the `index.html` file in your browser. You should see the UI we created. You can input a sample XML string like the following:</p> <pre><code><book> <title>Learn JavaScript</title> <author>Daniel Reed</author> <year>2023</year> </book></code></pre> <p>After entering the above XML and clicking on the “Parse XML” button, you should see the book information extracted and displayed. This interaction confirms that your XML parser is functioning correctly!</p> <h2>Handling Errors and Edge Cases</h2> <p>When working with user-generated XML, it's crucial to consider error handling. Users might input incorrectly formatted XML or completely invalid XML. We have already integrated basic error checking by looking for parser errors in our `parseXML` function. However, you may want to provide more detailed feedback to users. Consider adding a message that explains what went wrong if parsing fails.</p> <p>For example, update the error handling in your `parseXML` function to show a user-friendly message in the UI instead of just logging the error to the console. This improvement will enhance user experience and reduce confusion.</p> <h2>Expanding Your XML Parser</h2> <p>Your XML parser is just the beginning! There’s a lot you can do to enhance its functionality. For example, you could add support for attributes within elements, allow users to upload XML files, or even parse and manipulate larger XML structures. The possibilities are endless!</p> <p>In addition, consider creating a library or a reusable module that can be shared and utilized across various web applications. By modularizing your parser, you can ensure that it’s easy to maintain and extend in the future.</p> <h2>Conclusion</h2> <p>Congratulations on building your own XML parser using JavaScript! We've explored important concepts from setting up your development environment to handling user interactions and extracting data. Understanding how to parse XML is a valuable skill that can greatly enhance your web applications and data management capabilities.</p> <p>Keep experimenting with your new parser and think creatively about how you can apply this knowledge in real-world projects. Remember, technology is always evolving, so stay curious and continue learning. Happy coding!</p> </div><!-- .entry-content .clear --> </div> </article><!-- #post-## --> <nav class="navigation post-navigation" aria-label="Post navigation"> <span class="screen-reader-text">Post navigation</span> <div class="nav-links"><div class="nav-previous"><a title="Convert JavaScript Object to String: A Complete Guide" href="https://www.succeedjavascript.com/convert-javascript-object-to-string-a-complete-guide/" rel="prev"><span class="ast-post-nav"><span aria-hidden="true" class="ahfb-svg-iconset ast-inline-flex svg-baseline"><svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'><path d='M134.059 296H436c6.627 0 12-5.373 12-12v-56c0-6.627-5.373-12-12-12H134.059v-46.059c0-21.382-25.851-32.09-40.971-16.971L7.029 239.029c-9.373 9.373-9.373 24.569 0 33.941l86.059 86.059c15.119 15.119 40.971 4.411 40.971-16.971V296z'></path></svg></span> Previous</span> <p> Convert JavaScript Object to String: A Complete Guide </p></a></div><div class="nav-next"><a title="Understanding JavaScript Pass by Reference" href="https://www.succeedjavascript.com/understanding-javascript-pass-by-reference/" rel="next"><span class="ast-post-nav">Next <span aria-hidden="true" class="ahfb-svg-iconset ast-inline-flex svg-baseline"><svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'><path d='M313.941 216H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12h301.941v46.059c0 21.382 25.851 32.09 40.971 16.971l86.059-86.059c9.373-9.373 9.373-24.569 0-33.941l-86.059-86.059c-15.119-15.119-40.971-4.411-40.971 16.971V216z'></path></svg></span></span> <p> Understanding JavaScript Pass by Reference </p></a></div></div> </nav><div class="ast-single-related-posts-container ast-container--"><div class="ast-related-posts-title-section"> <h2 class="ast-related-posts-title"> Related Posts </h2> </div><div class="ast-related-posts-wrapper"> <article class="ast-related-post post-1398 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/empowering-women-in-tech-the-rise-of-female-react-developers/" target="_self" rel="bookmark noopener noreferrer">Empowering Women in Tech: The Rise of Female React Developers</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1811 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/mastering-object-oriented-programming-in-javascript/" target="_self" rel="bookmark noopener noreferrer">Mastering Object-Oriented Programming in JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 5, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1973 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/understanding-the-basics-of-javascript-why-does-not-equal-matters/" target="_self" rel="bookmark noopener noreferrer">Understanding the Basics of JavaScript: Why ‘Does Not Equal’ Matters</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 5, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-694 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/mastering-object-property-deletion-in-javascript/" target="_self" rel="bookmark noopener noreferrer">Mastering Object Property Deletion in JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1093 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/exploring-reactions-of-lithium-nitrate-with-various-solutions/" target="_self" rel="bookmark noopener noreferrer">Exploring Reactions of Lithium Nitrate with Various Solutions</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-2041 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/unlocking-javascript-mastery-insights-from-javascript-the-good-parts/" target="_self" rel="bookmark noopener noreferrer">Unlocking JavaScript Mastery: Insights from ‘JavaScript: The Good Parts’</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 5, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1962 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/mastering-undefined-variables-in-javascript/" target="_self" rel="bookmark noopener noreferrer">Mastering Undefined Variables in JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 5, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-2352 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/how-to-use-exit-statement-in-javascript-for-foreach-loops/" target="_self" rel="bookmark noopener noreferrer">How to Use exit Statement in JavaScript for foreach Loops</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 6, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-278 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/mastering-the-if-condition-in-javascript/" target="_self" rel="bookmark noopener noreferrer">Mastering the If Condition in JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-366 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/getting-started-with-aws-glue-sdk-for-javascript/" target="_self" rel="bookmark noopener noreferrer">Getting Started with AWS Glue SDK for JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-607 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/how-to-modify-css-styles-of-grid-elements-with-javascript/" target="_self" rel="bookmark noopener noreferrer">How to Modify CSS Styles of Grid Elements with JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1772 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/controlling-javascripts-setinterval-execute-code-after-completion/" target="_self" rel="bookmark noopener noreferrer">Controlling JavaScript’s setInterval: Execute Code After Completion</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 5, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1288 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/anesthesia-and-iron-supplements-understanding-interactions/" target="_self" rel="bookmark noopener noreferrer">Anesthesia and Iron Supplements: Understanding Interactions</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-920 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/mastering-object-property-removal-in-javascript/" target="_self" rel="bookmark noopener noreferrer">Mastering Object Property Removal in JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-444 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/getting-value-from-textbox-in-javascript-a-comprehensive-guide/" target="_self" rel="bookmark noopener noreferrer">Getting Value from Textbox in JavaScript: A Comprehensive Guide</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1380 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/integrating-viper-architecture-in-your-react-native-app/" target="_self" rel="bookmark noopener noreferrer">Integrating Viper Architecture in Your React Native App</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-1175 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/next-js-react-image-upload-preview-a-complete-guide/" target="_self" rel="bookmark noopener noreferrer">Next.js React Image Upload Preview: A Complete Guide</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-2501 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/how-to-check-if-a-string-exists-in-javascript-a-comprehensive-guide/" target="_self" rel="bookmark noopener noreferrer">How to Check if a String Exists in JavaScript: A Comprehensive Guide</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 8, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-129 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/cross-linking-web-pages-techniques-without-javascript/" target="_self" rel="bookmark noopener noreferrer">Cross-Linking Web Pages: Techniques Without JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 4, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> <article class="ast-related-post post-2169 post type-post status-publish format-standard hentry category-uncategorized"> <div class="ast-related-posts-inner-section"> <div class="ast-related-post-content"> <div class="ast-related-post-featured-section ast-no-thumb"></div> <header class="entry-header related-entry-header"> <h3 class="ast-related-post-title entry-title"> <a href="https://www.succeedjavascript.com/understanding-the-equality-operators-does-not-equal-in-javascript/" target="_self" rel="bookmark noopener noreferrer">Understanding the Equality Operators: Does Not Equal in JavaScript</a> </h3> <div class="entry-meta ast-related-cat-style--none ast-related-tag-style--none"><span class="posted-on"><span class="published" itemprop="datePublished"> January 5, 2025 </span></span></div> </header> <div class="entry-content clear"> </div> </div> </div> </article> </div> </div> </main><!-- #main --> </div><!-- #primary --> </div> <!-- ast-container --> </div><!-- #content --> <footer class="site-footer" id="colophon" itemtype="https://schema.org/WPFooter" itemscope="itemscope" itemid="#colophon"> <div class="site-below-footer-wrap ast-builder-grid-row-container site-footer-focus-item ast-builder-grid-row-full ast-builder-grid-row-tablet-full ast-builder-grid-row-mobile-full ast-footer-row-stack ast-footer-row-tablet-stack ast-footer-row-mobile-stack" data-section="section-below-footer-builder"> <div class="ast-builder-grid-row-container-inner"> <div class="ast-builder-footer-grid-columns site-below-footer-inner-wrap ast-builder-grid-row"> <div class="site-footer-below-section-1 site-footer-section site-footer-section-1"> <div class="ast-builder-layout-element ast-flex site-footer-focus-item ast-footer-copyright" data-section="section-footer-builder"> <div class="ast-footer-copyright"><p>Copyright © 2025 Succeed JS</p> </div> </div> </div> </div> </div> </div> </footer><!-- #colophon --> </div><!-- #page --> <div id="ast-scroll-top" tabindex="0" class="ast-scroll-top-icon ast-scroll-to-top-right" data-on-devices="both"> <span class="ast-icon icon-arrow"><svg class="ast-arrow-svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" width="26px" height="16.043px" viewBox="57 35.171 26 16.043" enable-background="new 57 35.171 26 16.043" xml:space="preserve"> <path d="M57.5,38.193l12.5,12.5l12.5-12.5l-2.5-2.5l-10,10l-10-10L57.5,38.193z"/> </svg></span> <span class="screen-reader-text">Scroll to Top</span> </div> <script src="https://www.succeedjavascript.com/wp-includes/js/comment-reply.min.js?ver=6.7.1" id="comment-reply-js" async data-wp-strategy="async"></script> <script id="astra-theme-js-js-extra"> var astra = {"break_point":"921","isRtl":"","is_scroll_to_id":"1","is_scroll_to_top":"1","is_header_footer_builder_active":"1","responsive_cart_click":"flyout"}; </script> <script src="https://www.succeedjavascript.com/wp-content/themes/astra/assets/js/minified/frontend.min.js?ver=4.8.9" id="astra-theme-js-js"></script> <script> /(trident|msie)/i.test(navigator.userAgent)&&document.getElementById&&window.addEventListener&&window.addEventListener("hashchange",function(){var t,e=location.hash.substring(1);/^[A-z0-9_-]+$/.test(e)&&(t=document.getElementById(e))&&(/^(?:a|select|input|button|textarea)$/i.test(t.tagName)||(t.tabIndex=-1),t.focus())},!1); </script> </body> </html> <!-- Page cached by LiteSpeed Cache 6.5.4 on 2025-01-10 06:51:33 --><script src="/cdn-cgi/scripts/7d0fa10a/cloudflare-static/rocket-loader.min.js" data-cf-settings="895375c492fb535c9c0a3c12-|49" defer></script>