XPATH / XSLT:选择父节点的属性与另一个节点的属性匹配的节点

时间:2011-03-29 12:55:13

标签: xml xslt xpath

我正在尝试使用XPath和XSLT将转换应用于以下XML。

<AuthorGroup>
  <Author AffiliationID="A1">
    <GivenName>John</GivenName>
    <Initials/>
    <FamilyName>Smith</FamilyName>
    <Degrees/>
    <Roles/>
  </Author>
    <Author AffiliationID="A2">
    <GivenName>Bill</GivenName>
    <Initials/>
    <FamilyName>Atkins</FamilyName>
    <Degrees/>
    <Roles/>
  </Author>
  <Affiliation AFFID="A1">
    <OrgDivision/>
    <OrgName>Some Org</OrgName>
    <OrgAddress/>
  </Affiliation>
  <Affiliation AFFID="A2">
    <OrgDivision/>
    <OrgName>Another Org</OrgName>
    <OrgAddress/>
  </Affiliation>
</AuthorGroup>

我正在尝试将作者和联盟名称合并到一个节点下,因此我最终会得到如下结构:

<AUG>
  <AU><NAME>John Smith</NAME><AUINFO>Some Org</AUINFO></AU>
  <AU><NAME>Bill Atkins</NAME><AUINFO>Another Org</AUINFO></AU>
</AUG>

我很难找到一种方法来选择父节点的属性与另一个节点的属性值匹配的节点的值。例如,对于作者John Smith,我想选择联属ID匹配的节点的值。

到目前为止,我的样式表中有一些代码,如下所示,但我知道节点内的选择不起作用。

<xsl:for-each select="AuthorGroup/Author">
  <AU>
  <NAME><xsl:value-of select="./FamilyName" /> <xsl:value-of select="./GivenName" /></NAME>
  <AUINFO><xsl:value-of select="../Affiliation[@AFFID='NEED TO MATCH AUTHOR AFFILIATIONID']/OrgName" /> </AUINFO>


  </AU>         
</xsl:for-each>

如何为关联作者选择正确的组织名称的值?

非常感谢

吉姆

4 个答案:

答案 0 :(得分:7)

作为使用变量的替代方法,您可以使用“current()”运算符来获取当前的作者节点

<xsl:value-of select="../Affiliation[@AFFID=current()/@AffiliationID]/OrgName"/>

因此,如果您采用以下样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:template match="/">
      <AUG>
         <xsl:for-each select="AuthorGroup/Author">
            <AU>
               <NAME>
                  <xsl:value-of select="./FamilyName"/>
                  <xsl:value-of select="./GivenName"/>
               </NAME>
               <AUINFO>
                  <xsl:value-of select="../Affiliation[@AFFID=current()/@AffiliationID]/OrgName"/>
               </AUINFO>
            </AU>
         </xsl:for-each>
      </AUG>
   </xsl:template>
</xsl:stylesheet>

并将其应用于您给定的XML,结果应该是这样的

<AUG>
   <AU>
      <NAME>SmithJohn</NAME>
      <AUINFO>Some Org</AUINFO>
   </AU>
   <AU>
      <NAME>AtkinsBill</NAME>
      <AUINFO>Another Org</AUINFO>
   </AU>
</AUG>

答案 1 :(得分:4)

键是交叉引用的正确工具。这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:key name="kAffiliationByAFFID" match="Affiliation" use="@AFFID"/>
    <xsl:template match="AuthorGroup">
        <AUG>
            <xsl:apply-templates/>
        </AUG>
    </xsl:template>
    <xsl:template match="Author">
        <AU>
            <NAME>
                <xsl:value-of select="concat(GivenName,' ',FamilyName)"/>
            </NAME>
            <xsl:apply-templates
                 select="key('kAffiliationByAFFID',@AffiliationID)"
                 mode="out"/>
        </AU>
    </xsl:template>
    <xsl:template match="Affiliation"/>
    <xsl:template match="Affiliation" mode="out">
        <AUINFO>
            <xsl:apply-templates/>
        </AUINFO>
    </xsl:template>
</xsl:stylesheet>

输出:

<AUG>
    <AU>
        <NAME>John Smith</NAME>
        <AUINFO>Some Org</AUINFO>
    </AU>
    <AU>
        <NAME>Bill Atkins</NAME>
        <AUINFO>Another Org</AUINFO>
    </AU>
</AUG>

答案 2 :(得分:2)

快速回答...希望这有帮助,暂时无法自己运行:-S 您可以将ID放在如下变量中:

<xsl:for-each select="AuthorGroup/Author">
  <xsl:variable name="affID" select="@AFFID" />
  <AU>
    <NAME><xsl:value-of select="./FamilyName" /> <xsl:value-of select="./GivenName" /></NAME>
    <AUINFO><xsl:value-of select="../Affiliation[@AFFID=$affID]/OrgName" /> </AUINFO>
  </AU>         
</xsl:for-each>

答案 3 :(得分:1)

<xsl:for-each select="AuthorGroup/Author">
    <AU>
    <NAME><xsl:value-of select="./FamilyName" /> <xsl:value-of select="./GivenName" />
    </NAME>
     <AUINFO><xsl:value-of select="../Affiliation[@AFFID=./@AffiliationID]/OrgName" /> 
     </AUINFO>