Xpath-如何获取所有现有属性的同级名称

时间:2019-02-28 11:29:56

标签: xslt xpath

目标很简单。我正在尝试建立具有列属性的表。

我的问题:某些兄弟姐妹的属性与第一个兄弟姐妹的属性不同。 构建表头时,我检索第一个节点的属性名称,然后希望以下同级的属性以相同的顺序相同。事实并非如此。 我只得到id, key, value, myattr1列,并且myattr2属性位于myattr1列中。

要构建表格,我想获取列:id, key, value, myattr1, myattr2

如何获取正在处理的节点的现有属性的整个列表并在其上循环?

我仍在使用相同的js和表格(请参阅底部的链接)。现在,它需要引导程序(css和js)。

我稍微更改了xml。这是:

<?xml version="1.0" encoding="UTF-8"?>
<Domain>
  <Properties id="myid">
    <Property id="DOM00000" key="mykey1" value="value1" myattr2="Mail"/>
    <Property id="DOM00001" key="mykey2" value="value2" myattr1="EveryDay"/>
  </Properties>
  <Tokens>
    <Token name="token1" comment="" ><![CDATA[mydata1---blah-blah-blah]]></Token>
    <Token name="token2" comment="" ><![CDATA[mydata2---blah-blah-blah]]></Token>
  </Tokens>
  <Resources>
    <Resource name="res1" type="W" current="0">
      <Value><![CDATA[10]]></Value>
    </Resource>
    <Resource name="res2" type="W" current="0">
      <Value><![CDATA[10]]></Value>
    </Resource>
  </Resources>
</Domain>

xsl的当前状态:

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

<xsl:template match="/*">
    <xsl:element name="div">
        <xsl:attribute name="class">container</xsl:attribute>
        <ul class="nav nav-tabs">
            <xsl:for-each select="./*">
                <xsl:call-template name="tabs" />
            </xsl:for-each>
        </ul>
    </xsl:element>
    <xsl:element name="div">
    <xsl:attribute name="class">tab-content</xsl:attribute>
        <xsl:for-each select="./*">
                <xsl:call-template name="tabcontent" />
        </xsl:for-each> 
    </xsl:element>
</xsl:template>


<xsl:template name="tabs">
    <xsl:variable name="active">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:element name="li">
        <xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
        <xsl:element name="a">
            <xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
            <xsl:attribute name="class">nav-link</xsl:attribute>
            <xsl:attribute name="data-toggle">tab</xsl:attribute>
            <xsl:value-of select="name(.)" />
        </xsl:element>

    </xsl:element>      
</xsl:template>

<xsl:template name="tabcontent">
    <xsl:variable name="activetab">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active in</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:element name="div">
        <xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
        <xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
        <h3><xsl:value-of select="name(.)" /></h3>
        <table class="table table-striped table-hover">
            <thead>
                <tr><xsl:for-each select="./*[1]/@*"><th><xsl:value-of select="name(.)" /></th></xsl:for-each></tr>
            </thead>
            <tbody>
                <xsl:for-each select="./*"><tr>
                    <xsl:for-each select="./@*"><td><xsl:value-of select="." /></td></xsl:for-each></tr>
                </tr></xsl:for-each>
            </tbody>
        </table>
    </xsl:element>
</xsl:template>

</xsl:stylesheet> 

XSLT - How to manage CDATA as common content?

编辑:

感谢Tim-C的回答 这是适用于我的用例的完整xsl:

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

<xsl:key name="attrs" match="/*/*/*/@*" use="concat(name(../..), '|', name())" />   

<xsl:template match="/*">
    <xsl:element name="div">
        <xsl:attribute name="class">container</xsl:attribute>
        <ul class="nav nav-tabs">
            <xsl:for-each select="./*">
                <xsl:call-template name="tabs" />
            </xsl:for-each>
        </ul>
    </xsl:element>
    <xsl:element name="div">
    <xsl:attribute name="class">tab-content</xsl:attribute>
        <xsl:for-each select="./*">
                <xsl:call-template name="tabcontent" />
        </xsl:for-each> 
    </xsl:element>
</xsl:template>


<xsl:template name="tabs">
    <xsl:variable name="active">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:element name="li">
        <xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
        <xsl:element name="a">
            <xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
            <xsl:attribute name="class">nav-link</xsl:attribute>
            <xsl:attribute name="data-toggle">tab</xsl:attribute>
            <xsl:value-of select="name(.)" />
        </xsl:element>

    </xsl:element>      
</xsl:template>

<xsl:template name="tabcontent">
    <xsl:variable name="activetab">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active in</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="attrs" select="*/@*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
    <xsl:element name="div">
        <xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
        <xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
        <h3><xsl:value-of select="name(.)" /></h3>
        <table class="table table-striped table-hover">
        <thead>
            <tr>
                <xsl:for-each select="$attrs">
                <th>
                    <xsl:value-of select="name()" />
                </th>
                </xsl:for-each>
            </tr>
        </thead>
        <tbody>
            <xsl:for-each select="*">
            <tr>
                <xsl:variable name="current" select="." />
                <xsl:for-each select="$attrs">
                <td>
                    <xsl:value-of select="$current/@*[name() = name(current())]" />
                </td>
                </xsl:for-each>
            </tr>
            </xsl:for-each>
        </tbody>
  </table>
    </xsl:element>
</xsl:template>

<xsl:template name="toto"></xsl:template>




</xsl:stylesheet> 

1 个答案:

答案 0 :(得分:1)

您在这里使用的是一种称为Muenchian分组的技术,该技术可根据其名称获取不同属性的列表。

但是,尽管问题仅提到id, key, value, myattr1, myattr2,它们是Property属性,但是您似乎也想在TokenResource节点上重复它(即,您正在尝试变得通用)。在这种情况下,您可以这样定义键,其中要考虑主要元素名称

<xsl:key name="attrs" match="/*/*/*/@*" use="concat(name(../..), '|', name())" />

然后,对于给定的元素(例如Properties),您可以像这样获得独特的属性:

<xsl:variable name="attrs" select="*/@*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />

然后可以使用它获取标题,并访问每一行的相关属性。

尝试(简化)的XSLT:

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

<xsl:key name="attrs" match="/*/*/*/@*" use="concat(name(../..), '|', name())" />

<xsl:template match="/*">
  <xsl:for-each select="*">
    <xsl:call-template name="tabcontent" />
  </xsl:for-each> 
</xsl:template>

<xsl:template name="tabcontent">
  <xsl:variable name="attrs" select="*/@*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
  <table class="table table-striped table-hover">
    <thead>
      <tr>
        <xsl:for-each select="$attrs">
          <th>
            <xsl:value-of select="name()" />
          </th>
        </xsl:for-each>
      </tr>
    </thead>
    <tbody>
      <xsl:for-each select="*">
        <tr>
          <xsl:variable name="current" select="." />
          <xsl:for-each select="$attrs">
            <td>
              <xsl:value-of select="$current/@*[name() = name(current())]" />
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </tbody>
  </table>
</xsl:template>
</xsl:stylesheet> 

http://xsltfiddle.liberty-development.net/jyRYYi7上查看它的运行情况

相关问题