3

我是 XSLT 的新手,我不明白为什么 root 会被处理两次(至少这是我对此输出的解释)。

编辑:(我将 Saxon-HE 与 XSLT 2.0 一起使用)但也使用了几个在线流程进行了测试,总是得到相同的结果。

XSLT 文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- XResume.xsl: resume.xml ==> resume.xhtml -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="https://github.com/IME-SE8/XResume">

<xsl:output method="html"/>

<xsl:template match="/">

<html>
<head>
  <meta charset="utf-8" />
  <meta lang="en" />
  <meta name="description" content="Personal Resume and Portfolio" />
  <title><xsl:value-of select="resume/personalInformation/name/attribute::shortForm" /> Website</title>
</head>
<body>
  <xsl:apply-templates select="resume"/>
</body>
</html>

</xsl:template>

<xsl:template match="resume">
  <div class="resume">

    <div class="header">
      <div class="name"><xsl:value-of select="personalInformation/name" /></div>
      <div class="contacts">
        <xsl:for-each select="personalInformation/contact">
          <div class="contactInformation">
            <p><xsl:value-of select="organization" /></p>
            <p><xsl:value-of select="address" /></p>
            <p><xsl:value-of select="phoneNumber" /></p>
            <p><xsl:value-of select="email" /></p>
          </div>
        </xsl:for-each>
      </div>
    </div>

    <div class="sections">
      <xsl:apply-templates />
    </div>
  </div>
</xsl:template>


<xsl:template match="interests"></xsl:template>
<xsl:template match="education"></xsl:template>
<xsl:template match="skills"></xsl:template>
<xsl:template match="experiences"></xsl:template>
<xsl:template match="projects"></xsl:template>
<xsl:template match="awards"></xsl:template>

</xsl:stylesheet>

XML 文件

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl"
href="https://github.com/IME-SE8/XResume/master/XResume.xsl"?>
<resume 
xmlns="https://github.com/IME-SE8/XResume" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://github.com/IME-SE8/XResume XResume.xsd">

    <personalInformation>
        <name first="John" last="Doe" shortForm="JD">John Doe</name>
        <contact type="institutional">
            <organization>StackOverflow Institute of Technology</organization>
            <address>Internet</address>
            <phoneNumber>+1 (666) 666-9999</phoneNumber>
            <email>john@d.oe</email>
        </contact>
    </personalInformation>


    <interests>
        <interest>Q and A</interest>
        <interest>XSLT</interest>
    </interests>

    <education></education>

    <skills></skills>

    <experiences></experiences>

    <projects></projects>

    <awards></awards>

</resume>

HTML 输出

<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta charset="utf-8">
      <meta lang="en">
      <meta name="description" content="Personal Resume and Portfolio">
      <title>JD Website</title>
   </head>
   <body>
      <div class="resume">
         <div class="header">
            <div class="name">John Doe</div>
            <div class="contacts">
               <div class="contactInformation">
                  <p>StackOverflow Institute of Technology</p>
                  <p>Internet</p>
                  <p>+1 (666) 666-9999</p>
                  <p>john@d.oe</p>
               </div>
            </div>
         </div>
         <div class="sections">


                    John Doe

                        StackOverflow Institute of Technology
                        Internet
                        +1 (666) 666-9999
                        john@d.oe

















         </div>
      </div>
   </body>
</html>

(是的,有这么多的空行)

输出header div非常好,但在里面sections div呈现apply-templates了所有信息,div header但没有 HTML 标记。

我是否缺少任何 XSLT 处理细节?模板匹配是否以匹配元素现在被视为根或类似的方式设置上下文?

4

3 回答 3

1

问题在这里:

<div class="sections">
  <xsl:apply-templates />
</div>

这会将模板应用于当前节点 ( resume) 的所有子节点,包括personalInformation元素。

由于没有为 指定匹配personalInformation的模板,XSLT 处理器使用内置的 XSLT 模板,应用它们会导致输出personalInformation元素的所有后代文本节点的连接。

解决方案

代替:

<div class="sections">
  <xsl:apply-templates />
</div>

和:

<div class="sections">
  <xsl:apply-templates select="*[not(self::personalInformation)]" />
</div>

转换的结果现在不包含注意到的有问题的输出:

<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta charset="utf-8">
      <meta lang="en">
      <meta name="description" content="Personal Resume and Portfolio">
      <title>JD Website</title>
   </head>
   <body>
      <div class="resume">
         <div class="header">
            <div class="name">John Doe</div>
            <div class="contacts">
               <div class="contactInformation">
                  <p>StackOverflow Institute of Technology</p>
                  <p>Internet</p>
                  <p>+1 (666) 666-9999</p>
                  <p>john@d.oe</p>
               </div>
            </div>
         </div>
         <div class="sections"></div>
      </div>
   </body>
</html>
于 2015-10-18T04:37:58.823 回答
0

你没有提供预期的输出,所以我会猜测你的预期结果。这是一个 XSLT 2.0 解决方案。如果您需要 XSLT 1.0,请发表评论,我可以添加。但请记住,如果您的转换引擎是浏览器,那么您没有理由不使用 XSLT 2.0。(参见撒克逊 CE)。

XSLT 2.0 解决方案

这个 XSLT 2.0 样式表...

<xsl:transform
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:r="https://github.com/IME-SE8/XResume" 
    exclude-result-prefixes="r"
    version="2.0">

<xsl:output method="html" version="5" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="/">
  <html>
    <head>
      <meta lang="en" />
      <meta name="description" content="Personal Resume and Portfolio" />
      <title><xsl:value-of select="r:resume/r:personalInformation/r:name/@shortForm" /> Website</title>
    </head>
    <body>
      <xsl:apply-templates select="r:resume"/>
    </body>
  </html>
</xsl:template>

<xsl:template match="r:resume">
  <div class="resume">
    <div class="header">
      <div class="name"><xsl:value-of select="r:personalInformation/r:name" /></div>
      <div class="contacts">
        <xsl:apply-templates select="r:personalInformation/r:contact" />
      </div>
    </div>
    <div class="sections">
      <xsl:apply-templates select="* except r:personalInformation" />
    </div>
  </div>      
</xsl:template>

<xsl:template match="r:contact">
  <div class="contactInformation">
    <xsl:apply-templates />
  </div>
</xsl:template>

<xsl:template match="r:organization|r:address|r:phoneNumber|r:email">
  <p><xsl:value-of select="." /></p>
</xsl:template>

<xsl:template match="r:education|r:skills|r:experiences|r:projects|r:awards">
  <h2><xsl:value-of select="local-name()" /></h2>
  <p><xsl:value-of select="." /></p>
</xsl:template>

<xsl:template match="r:interests">
  <h2>interests</h2>
  <ul>
    <xsl:apply-templates />
  </ul>
</xsl:template>

<xsl:template match="r:interest">
  <li>
    <xsl:value-of select="." />
  </li>
</xsl:template>

<xsl:template match="*" />

</xsl:transform>

...应用于此输入文档时...

<resume 
    xmlns="https://github.com/IME-SE8/XResume" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://github.com/IME-SE8/XResume XResume.xsd">

    <personalInformation>
        <name first="John" last="Doe" shortForm="JD">John Doe</name>
        <contact type="institutional">
            <organization>StackOverflow Institute of Technology</organization>
            <address>Internet</address>
            <phoneNumber>+1 (666) 666-9999</phoneNumber>
            <email>john@d.oe</email>
        </contact>
    </personalInformation>


    <interests>
        <interest>Q and A</interest>
        <interest>XSLT</interest>
    </interests>

    <education></education>

    <skills></skills>

    <experiences></experiences>

    <projects></projects>

    <awards></awards>

</resume>

... 将产生此输出 html 页面 ....

<!DOCTYPE HTML>
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta lang="en">
      <meta name="description" content="Personal Resume and Portfolio">
      <title>JD Website</title>
   </head>
   <body>
      <div class="resume">
         <div class="header">
            <div class="name">John Doe</div>
            <div class="contacts">
               <div class="contactInformation">
                  <p>StackOverflow Institute of Technology</p>
                  <p>Internet</p>
                  <p>+1 (666) 666-9999</p>
                  <p>john@d.oe</p>
               </div>
            </div>
         </div>
         <div class="sections">
            <h2>interests</h2>
            <ul>
               <li>Q and A</li>
               <li>XSLT</li>
            </ul>
            <h2>education</h2>
            <p></p>
            <h2>skills</h2>
            <p></p>
            <h2>experiences</h2>
            <p></p>
            <h2>projects</h2>
            <p></p>
            <h2>awards</h2>
            <p></p>
         </div>
      </div>
   </body>
</html>

说明:为什么您要对 root 进行两次处理

简而言之,因为您的<div class="sections"><xsl:apply-templates /></div>指令没有指定选择属性。应用了默认选择,即当时的文档根目录。

于 2015-10-13T06:33:13.850 回答
0

源文档中的所有元素都在一个命名空间中,但是您的样式表是为处理没有命名空间中的元素而编写的。欢迎加入俱乐部,加入其他 1000 万掉入这个陷阱的人。本质上,您的简历元素与 match="resume" 模板不匹配,因此默认模板启动,这会输出没有标签的原始文本。对于解决方案,搜索“XSLT 默认命名空间”并选择大约 1000 个答案中的任何一个。

在重新阅读时,我看到您使用过xpath-default-namespace="https://github.com/IME-SE8/XResume",如果您使用的是 XSLT 2.0 处理器,它应该可以解决问题,或者如果您使用的是 XSLT 1.0 处理器,则会触发错误。因此,告诉我们您正在使用什么处理器以及您如何运行它可能很有用(实际上,它总是有用的)。

于 2015-10-13T07:48:53.157 回答