没有孩子的xslt副本

时间:2011-01-25 11:44:33

标签: xslt attributes nodes

喜 我有一个看起来像这样的站点地图xml文档

<pagenode title="home" url="~/" fornavbar="true">
 <pagenode title="admin" url="~/admin" fornavbar="false">
  <pagenode title="users" url="~/admin/users" fornavbar="false"/>
  <pagenode title="events" url="~/admin/events" fornavbar="true"/>
 </pagenode>
 <pagenode title="catalog" url="~/catalog" fornavbar="true"/>
 <pagenode title="contact us" url="~/contactus" fornavbar="false"/>
</pagenode>

现在我想检索导航栏的xml文档,其中包含所有具有fornavbar = true的页面节点。怎么办呢?

到目前为止,我能得到的最接近的是:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="pagenode[@fornavbar='true']">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

这个问题包括所有匹配为navbar的孩子

我只想复制所有属性,而不是所有的孩子

但如果我尝试

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="pagenode[@fornavbar='true']">
  <pagenode title="{@title}"  url="{@url}"/>
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

然后我有2个问题

  1. 我可能会单独输入每个属性,而且我每页都会有很多属性,并且最终会发生变化
  2. 它失去了层次结构。一切都变得扁平了
  3. 我将非常感谢此事的所有帮助。

    谢谢你!

    编辑:id喜欢看的示例输出

    <pagenode title="home" url="~/" fornavbar="true">
     <pagenode title="events" url="~/admin/events" fornavbar="true"/>
     <pagenode title="catalog" url="~/catalog" fornavbar="true"/>
    </pagenode>
    

3 个答案:

答案 0 :(得分:3)

这可能是最短最纯粹的XSLT解决方案:

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

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="*[@fornavbar = 'false']">
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<pagenode title="home" url="~/" fornavbar="true">
    <pagenode title="admin" url="~/admin" fornavbar="false">
        <pagenode title="users" url="~/admin/users" fornavbar="false"/>
        <pagenode title="events" url="~/admin/events" fornavbar="true"/>
    </pagenode>
    <pagenode title="catalog" url="~/catalog" fornavbar="true"/>
    <pagenode title="contact us" url="~/contactus" fornavbar="false"/>
</pagenode>

产生了想要的正确结果:

<pagenode title="home" url="~/" fornavbar="true">
   <pagenode title="events" url="~/admin/events" fornavbar="true"/>
   <pagenode title="catalog" url="~/catalog" fornavbar="true"/>
</pagenode>

<强>解释

  1. 标识规则(模板)按“原样”复制每个节点。使用 identity rule 并覆盖它是最基本的XSLT设计模式。

  2. 有一个模板可以覆盖身份规则 - 适用于fornavbar属性为"false"的元素。这里指定的操作是对当前元素的子元素应用模板。

答案 1 :(得分:2)

您可以使用xsl:foreach select="@*"迭代节点的属性 这样您就不必手动复制属性。如果你致电xsl:apply-templates 在yor pagenode元素内部,您应该得到所需的结果。

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="pagenode[@fornavbar='true']">
        <pagenode>
            <xsl:for-each select="@*">
                <xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute>
            </xsl:for-each>
            <xsl:apply-templates/>
        </pagenode>
    </xsl:template>
</xsl:stylesheet>

制作

<?xml version="1.0"?>
<pagenode title="home" url="~/" fornavbar="true">
    <pagenode title="events" url="~/admin/events" fornavbar="true"/>
  <pagenode title="catalog" url="~/catalog" fornavbar="true"/>
</pagenode>

答案 2 :(得分:1)

XSLT应如下所示:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="pagenode[@fornavbar='true']">
    <pagenode>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </pagenode>
  </xsl:template>
</xsl:stylesheet>