如何用XSLT实现XML中不同书籍描述的指定格式展示?
Got it, dealing with variable book descriptions in XSLT is such a common pain point when working with flexible XML structures—here's how I've solved this exact problem before:
Core Idea: Ditch Hardcoding, Use XSLT's Template Matching
Instead of trying to write explicit rules for every possible description field (which breaks as soon as a new field is added), leverage XSLT's ability to match elements dynamically. This lets your stylesheet adapt to whatever fields exist in each book's entry.
Step 1: Update Your DTD (If Needed)
First, make sure your DTD allows flexible content in the description section so your XML stays valid. For example:
<!ELEMENT items (item+)> <!ELEMENT item (title, description)> <!ATTLIST item type CDATA #REQUIRED> <!ELEMENT title (#PCDATA)> <!-- Allow any combination of text and common book fields --> <!ELEMENT description (#PCDATA|author|year|publisher|isbn|summary|pages)*>
Step 2: XSLT Stylesheet for Dynamic Descriptions
This stylesheet will render each book as a card, and automatically display any description fields present—no matter which ones they are:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Match the root element and set up HTML output --> <xsl:template match="/"> <html> <head> <link rel="stylesheet" href="workshop.css"/> </head> <body> <h1>Ebook Collection</h1> <xsl:apply-templates select="items/item[@type='ebook']"/> </body> </html> </xsl:template> <!-- Match each ebook item and wrap it in a card --> <xsl:template match="item[@type='ebook']"> <div class="book-card"> <h2><xsl:value-of select="title"/></h2> <div class="book-description"> <!-- Apply templates to ALL child elements of description --> <xsl:apply-templates select="description/*"/> </div> </div> </xsl:template> <!-- Template for specific known fields (with custom styling hooks) --> <xsl:template match="description/author"> <p class="author-field"><strong>Author:</strong> <xsl:value-of select="."/></p> </xsl:template> <xsl:template match="description/year"> <p class="year-field"><strong>Published:</strong> <xsl:value-of select="."/></p> </xsl:template> <xsl:template match="description/publisher"> <p class="publisher-field"><strong>Publisher:</strong> <xsl:value-of select="."/></p> </xsl:template> <!-- Fallback template for ANY unknown description field --> <xsl:template match="description/*"> <p class="generic-field"> <!-- Capitalize the field name for readability --> <strong><xsl:value-of select="concat(upper-case(substring(local-name(),1,1)), substring(local-name(),2))"/>:</strong> <xsl:value-of select="."/> </p> </xsl:template> </xsl:stylesheet>
Step 3: CSS for Consistent Styling (Match Your Target Format)
Add this to your workshop.css to get clean, card-based rendering (adjust to match your desired image format):
body { font-family: Arial, sans-serif; max-width: 800px; margin: 2rem auto; padding: 0 1rem; } .book-card { border: 1px solid #e0e0e0; border-radius: 8px; padding: 1.5rem; margin-bottom: 1.5rem; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .book-card h2 { margin-top: 0; color: #2d3748; } .book-description p { margin: 0.75rem 0; font-size: 0.95rem; color: #4a5568; } .book-description strong { color: #2d3748; }
Why This Works
- Flexibility: If you add a new field like
<pages>or<language>to a book's description later, the fallback template will automatically render it without any changes to your XSLT. - Clean Markup: Each field gets a custom class for styling, so you can tweak individual field appearances easily.
- Valid XML: The DTD ensures your variable descriptions don't break XML validity.
内容的提问来源于stack exchange,提问作者Rizki

