如何在JavaScript中定位HTML列表元素的结束标签
Great question! Trying to find closing tags for list elements like <li>, <ol>, and <ul> directly with regex is a common trap—HTML’s nested structure makes regex unreliable. Instead, using the browser’s built-in DOMParser is the robust way to handle this. Here’s how to do it:
Step 1: Parse the HTML string into a DOM document
The DOMParser API lets you convert raw HTML into a fully structured DOM tree, which automatically handles nested elements and even fixes incomplete tags (like the truncated ones in your example).
Step 2: Extract all list elements and their closing tags
Once you have the DOM document, you can query for all list elements, then generate their corresponding closing tags. Here’s a complete code example:
// Your input HTML string (completed truncated parts for demonstration) const htmlString = `<h2>Actions</h2> <ol> <li> <p><span style="font-size: 12pt; font-family: arial,helvetica,sans-serif;"><strong>Find the Subscriber</strong></span></p> <ol style="list-style-type: decimal;"> <li>Sign in to RMS and click the <strong>Customer Search</strong> link.</li> <li>Enter the customer’s phone number in the <strong>PTN</strong> field and click <strong>Search</strong>.</li> <li>Authenticate the customer per standard procedures. Refer to <span style="color: #303030;"><a class="jive-link-wiki-small" data-containerid="2714" data-containertype="14" data-objectid="4592" data-objecttype="102" href="https://iconnect.sprint.com/docs/DOC-4592">Customer Authentication <span style="line-height: 107%; font-family: 'Calibri',sans-serif; font-size: 11pt; mso-ascii-theme-font: minor-latin; mso-hansi-theme-font: minor-latin; mso-bidi-font-family: 'Times New Roman'; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-ansi-language: EN-US; mso-fareast-theme-font: minor-latin; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;">–</span> Setting up Security Access Information</a></span> for steps.</li> <li>Navigate to the <strong>Services</strong> tab and click the <strong>Subscriber #</strong> link to open the <strong>Subscriber Information </strong>screen.</li> <li>On the <strong>Subscription Information </strong>screen, click <strong>Contract/Agreement Details</strong>.</li> <li>Verify that the correct PTN displays in the lower section of the screen with the <strong>Loan/Lease Details</strong>.</li> </ol> </li> </li> <li> <p><span style="font-size: 12pt; font-family: arial,helvetica,sans-serif;"><strong>Terminate the Lease</strong></span></p> <ol style="list-style-type: decimal;"> <li> Click <strong>Terminate Lease</strong>. <ul> <li> The <strong>Lease Termination</strong> screen will display the current, active ESN in the<strong> Incoming Device</strong> field. <ul> <li>If the customer doesn't have their original device but wants to turn in a device of equal or greater value to complete the transaction, check to make sure that device is, in fact, worth equal or greater value: Confirm the value by replacing the ESN in the <strong>Incoming Device</strong> field with the ESN of the device the customer wants to turn in.</li> </ul> </li> </ul> </li> <li> <strong>Review the two options with the customer:</strong><span style="font-family: Calibri;"> T</span>urn in the device or purchase it: <ol style="list-style-type: upper-alpha;"> <li> <strong>Turn in the device:</strong> <ol style="list-style-type: decimal;"> <li>Tell the customer the required payment and taxes that they'll owe.</li> <li>Inspect the device for damage.</li> <li> All turn-in devices must power on with no damage to the device. If it's an Apple device, make sure the Activation Lock is disabled. If the device is damaged, the customer can still turn in the device, but they'll be charged a <strong>Damaged Device Fee (DDF).</strong> <ul style="list-style-type: circle;"> <li><strong>Note:</strong> Damage to the device is defined as anything broken, cracked and missing (LCD, hinge, keypad, buttons, housing, battery door).</li> </ul> </li> <li> If the turn-in device doesn’t power on or is damaged, tell the customer their options: <ul> <li>If applicable, file an insurance claim or have the device repaired in-store. Deductibles and/or S&R fees may apply.</li> <li>Pay the associated DDF as displayed in RMS and turn in the device.</li> <li>Choose the Purchase option: Pay off the remaining balance on the current lease to become eligible for an upgrade without a turn-in.</li> </ul> </li> <li> If the turn-in device meets the criteria above, select the appropriate answers next to the questions in the drop-down list: <ul> <li>Does the device power on and off?</li> <li>Is anything broken, cracked, missing (LCD, hinge, keypad, buttons, housing, battery door)?</li> <li><strong>Note:</strong> The <strong>Continue</strong> button won't be enabled until you select the answers.</li> </ul> </li> </ol> </li> </ol> </li> </ol> </li>`; // Parse the HTML into a DOM document const parser = new DOMParser(); const doc = parser.parseFromString(htmlString, 'text/html'); // Grab all list-related elements const listElements = doc.querySelectorAll('li, ol, ul'); // Collect their closing tags const closingTags = []; listElements.forEach(element => { const tagName = element.tagName.toLowerCase(); closingTags.push(`</${tagName}>`); }); // Output the closing tags (customize display as needed) console.log('Collected closing tags:', closingTags);
Why avoid regex for this?
HTML isn’t a regular language—nested elements (like a <ul> inside an <li>) will trip up regex patterns, which can’t reliably match the correct closing tag for deeply nested elements. The DOMParser handles this natively because it understands HTML’s structure.
Caveat for locating closing tags in the original string
If you need to find the exact position of closing tags in your raw HTML string, this gets trickier. The DOMParser may fix incomplete tags (like adding missing </li> or </ul>) that don’t exist in your original input, which means the parsed DOM won’t perfectly align with the raw string. For this edge case, you’d need to combine string parsing with DOM analysis, but it’s far less reliable than working with the parsed DOM directly.
内容的提问来源于stack exchange,提问作者Dreams

