如何使用 XSLT 将特定类的未知 XML 元素格式化为 HTML?

发布于 2024-11-09 20:28:28 字数 1299 浏览 0 评论 0原文

所以我有一个由我的应用程序生成的 XML 文档,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE AddressBook>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<AddressBook>
 <Item>
  <UserGeneratedElementName1 class="info">Whatever blah blah</UserGeneratedElementName1>
  <UserGeneratedElementName2 class="info">Whatever blah blah</UserGeneratedElementName2>
 </Item>
 <Item>
  <UserGeneratedElementName3 class="info">Whatever blah blah</UserGeneratedElementName3>
 </Item>
 ...
 ...
 Other Items with user-generated elements with user-generated content...
</AddressBook>

我想将其转换为类似于此的 HTML 文档:

<html>
<head>
 <title>AddressBook</title>
</head>
<body>
 <div class="root">
  <div class="item">
   <b>UserGeneratedElementName1:</b> Whatever blah blah
   <b>UserGeneratedElementName2:</b> Whatever blah blah
  </div>
  <div class="item">
   <b>UserGeneratedElementName3:</b> Whatever blah blah
  </div>
  ...
  ...
  Other transformed items...
 </div>
</body>
</html>

我试图掌握 XSLT 语法,但所有指南都太模糊,无法帮助我跟这个还是太深了。另外,XSLT 语法似乎很混乱。 提前致谢。

So I have a XML document generated by my application like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE AddressBook>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<AddressBook>
 <Item>
  <UserGeneratedElementName1 class="info">Whatever blah blah</UserGeneratedElementName1>
  <UserGeneratedElementName2 class="info">Whatever blah blah</UserGeneratedElementName2>
 </Item>
 <Item>
  <UserGeneratedElementName3 class="info">Whatever blah blah</UserGeneratedElementName3>
 </Item>
 ...
 ...
 Other Items with user-generated elements with user-generated content...
</AddressBook>

And I want to turn it into a HTML document similar to this:

<html>
<head>
 <title>AddressBook</title>
</head>
<body>
 <div class="root">
  <div class="item">
   <b>UserGeneratedElementName1:</b> Whatever blah blah
   <b>UserGeneratedElementName2:</b> Whatever blah blah
  </div>
  <div class="item">
   <b>UserGeneratedElementName3:</b> Whatever blah blah
  </div>
  ...
  ...
  Other transformed items...
 </div>
</body>
</html>

I have tried to get a grasp of the XSLT syntax, but all the guides were either too vague to help me with this or too deep. Also XSLT syntax seems quite confusing.
Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏九 2024-11-16 20:28:28

在这里看看这个问题

是否有 XSLT name-of 元素?

您可以使用

<xsl:value-of select ="name(.)"/>

<xsl:value-of select ="local-name()"/>

来获取节点的名称,具体取决于您是要包含完整的前缀名称还是仅包含本地部分。

您应该能够使用 xsl:for-each 块将它们组合在一起,以迭代前 3 个级别的项目并生成您要查找的 HTML。

像这样的东西适用于固定数量的级别。

    <xsl:for-each select="*">
        <html>
            <head>
                <title><xsl:value-of select="local-name()" /></title>
            </head>
            <body>
                <div class="root">
                    <xsl:for-each select="*">
                        <div>
                            <xsl:attribute name="class">
                                <xsl:value-of select="local-name()" />
                            </xsl:attribute>
                            <xsl:for-each select="*">
                                <b><xsl:value-of select="local-name()" />:</b> <xsl:value-of select="." />
                            </xsl:for-each>
                        </div>
                    </xsl:for-each>
                </div>
            </body>
        </html>
    </xsl:for-each>

更通用的方法看起来更像是:

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0">

<xsl:output method="html" indent="yes" version="4.0"/>
<xsl:template match="/">
    <xsl:for-each select="*">
        <html>
            <head>
                <title><xsl:value-of select="local-name()" /></title>
            </head>
            <body>
                <div class="root">
                        <xsl:call-template name="recurseElement">
                            <xsl:with-param name="element" select="." />
                        </xsl:call-template>
                </div>
            </body>
        </html>
    </xsl:for-each>
</xsl:template>
<xsl:template name="recurseElement">
    <xsl:param name="element" />
    <xsl:for-each select="$element/*">
        <xsl:choose>
                <xsl:when test="count(child::*)>0">
                    <div>
                        <xsl:attribute name="class">
                            <xsl:value-of select="local-name()" />
                        </xsl:attribute>
                        <xsl:call-template name="recurseElement">
                            <xsl:with-param name="element" select="." />
                        </xsl:call-template>
                    </div>
                </xsl:when>
                <xsl:otherwise>
                    <b><xsl:value-of select="local-name()" />:</b> <xsl:value-of select="." />
                </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Take a look at this question here

Is there an XSLT name-of element?

You can use

<xsl:value-of select ="name(.)"/>

or

<xsl:value-of select ="local-name()"/>

to get the name of a node, depending on if you want to include the full prefixed name, or just the local portion.

You should be able to piece those together with xsl:for-each blocks to iterate through the first 3 levels of items and generate the HTML you're looking for.

Something like this would work for a fixed number of levels.

    <xsl:for-each select="*">
        <html>
            <head>
                <title><xsl:value-of select="local-name()" /></title>
            </head>
            <body>
                <div class="root">
                    <xsl:for-each select="*">
                        <div>
                            <xsl:attribute name="class">
                                <xsl:value-of select="local-name()" />
                            </xsl:attribute>
                            <xsl:for-each select="*">
                                <b><xsl:value-of select="local-name()" />:</b> <xsl:value-of select="." />
                            </xsl:for-each>
                        </div>
                    </xsl:for-each>
                </div>
            </body>
        </html>
    </xsl:for-each>

A more generic approach would look something more like:

<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0">

<xsl:output method="html" indent="yes" version="4.0"/>
<xsl:template match="/">
    <xsl:for-each select="*">
        <html>
            <head>
                <title><xsl:value-of select="local-name()" /></title>
            </head>
            <body>
                <div class="root">
                        <xsl:call-template name="recurseElement">
                            <xsl:with-param name="element" select="." />
                        </xsl:call-template>
                </div>
            </body>
        </html>
    </xsl:for-each>
</xsl:template>
<xsl:template name="recurseElement">
    <xsl:param name="element" />
    <xsl:for-each select="$element/*">
        <xsl:choose>
                <xsl:when test="count(child::*)>0">
                    <div>
                        <xsl:attribute name="class">
                            <xsl:value-of select="local-name()" />
                        </xsl:attribute>
                        <xsl:call-template name="recurseElement">
                            <xsl:with-param name="element" select="." />
                        </xsl:call-template>
                    </div>
                </xsl:when>
                <xsl:otherwise>
                    <b><xsl:value-of select="local-name()" />:</b> <xsl:value-of select="." />
                </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>
断桥再见 2024-11-16 20:28:28

此完整的 XSLT 转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="AddressBook">
  <html>
    <head>
     <title>AddressBook</title>
    </head>
    <body>
      <div class="root">
       <xsl:apply-templates/>
      </div>
    </body>
  </html>
 </xsl:template>

 <xsl:template match="Item">
  <div class="item"><xsl:apply-templates/></div>
 </xsl:template>

 <xsl:template match="Item/*">
  <b><xsl:value-of select="name()"/>:</b> <xsl:text/>
  <xsl:value-of select="concat(.,'
            ')"/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<AddressBook>
    <Item>
        <UserGeneratedElementName1 class="info">Whatever blah blah</UserGeneratedElementName1>
        <UserGeneratedElementName2 class="info">Whatever blah blah</UserGeneratedElementName2>
    </Item>
    <Item>
        <UserGeneratedElementName3 class="info">Whatever blah blah</UserGeneratedElementName3>
    </Item> ... ... Other Items with user-generated elements with user-generated content...
</AddressBook>

产生所需的正确结果

<html>
   <head>
      <title>AddressBook</title>
   </head>
   <body>
      <div class="root">
         <div class="item">
            <b>UserGeneratedElementName1:</b>Whatever blah blah
            <b>UserGeneratedElementName2:</b>Whatever blah blah
            </div>
         <div class="item">
            <b>UserGeneratedElementName3:</b>Whatever blah blah
            </div> ... ... Other Items with user-generated elements with user-generated content...
</div>
   </body>
</html>

说明

  1. 模板匹配任何Item 元素以及 Item 元素的任何子元素。

  2. 使用标准 XPath name() 函数

This complete XSLT transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="AddressBook">
  <html>
    <head>
     <title>AddressBook</title>
    </head>
    <body>
      <div class="root">
       <xsl:apply-templates/>
      </div>
    </body>
  </html>
 </xsl:template>

 <xsl:template match="Item">
  <div class="item"><xsl:apply-templates/></div>
 </xsl:template>

 <xsl:template match="Item/*">
  <b><xsl:value-of select="name()"/>:</b> <xsl:text/>
  <xsl:value-of select="concat(.,'
            ')"/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<AddressBook>
    <Item>
        <UserGeneratedElementName1 class="info">Whatever blah blah</UserGeneratedElementName1>
        <UserGeneratedElementName2 class="info">Whatever blah blah</UserGeneratedElementName2>
    </Item>
    <Item>
        <UserGeneratedElementName3 class="info">Whatever blah blah</UserGeneratedElementName3>
    </Item> ... ... Other Items with user-generated elements with user-generated content...
</AddressBook>

produces the wanted, correct result:

<html>
   <head>
      <title>AddressBook</title>
   </head>
   <body>
      <div class="root">
         <div class="item">
            <b>UserGeneratedElementName1:</b>Whatever blah blah
            <b>UserGeneratedElementName2:</b>Whatever blah blah
            </div>
         <div class="item">
            <b>UserGeneratedElementName3:</b>Whatever blah blah
            </div> ... ... Other Items with user-generated elements with user-generated content...
</div>
   </body>
</html>

Explanation:

  1. Templates matching any Item element and any element child of an Item element.

  2. Use of the standard XPath name() function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文