如何在XSLT中访问具有动态节点名称的节点的子节点

时间:2017-07-15 05:56:23

标签: xml xslt-1.0

我坚持这个问题。

我有这个XML:

<Document>
  <Type>ABC</Type>
  <Header>
    <Date>15-01-2017</Date>
    <Time>11:00 AM</Time>
  </Header>
  <Body>
    <Name>Juan</Name>
    <Age>10</Age>
    <Address>
      <City>City</City>
      <Country>Country</Country>
      <Block>Block</Block>
    </Address>
  </Body>
</Document>

我有这个XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>
  <xsl:variable name ="DocumentType" select ="//Document/Type" />

  <xsl:template match ="Document">
    <Root>
      <xsl:apply-templates select ="Header" />
      <xsl:element name="Data{$DocumentType}">
        <xsl:call-template name="Data">
          <xsl:with-param name="type" select ="$DocumentType" />
        </xsl:call-template>
      </xsl:element>
    </Root>
  </xsl:template>

  <xsl:template name ="Data">
    <xsl:param name="type" />
    <Name>
      <xsl:value-of select ="Body/Name" />
    </Name>
    <Age>
      <xsl:value-of select ="Body/Age" />
    </Age>
    <xsl:element name="Address{$type}">
      <City>
        <xsl:value-of select ="City"/>
      </City>
      <Country>
        <xsl:value-of select ="Country"/>
      </Country>
      <Block>
        <xsl:value-of select ="Block"/>
      </Block>
    </xsl:element>
  </xsl:template>

  <xsl:template match ="Header">
    <Header>
      <DateCreated>
        <xsl:value-of select ="Date"/>
      </DateCreated>
      <TimeCreated>
        <xsl:value-of select ="Time"/>
      </TimeCreated>
    </Header>
  </xsl:template>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

我的问题是我无法访问XML中地址的子节点的值,我只看到这个:

<Root>
  <Header>
    <DateCreated>15-01-2017</DateCreated>
    <TimeCreated>11:00 AM</TimeCreated>
  </Header>
  <DataABC>
    <Name>Juan</Name>
    <Age>10</Age>
    <AddressABC>
      <City></City>
      <Country></Country>
      <Block></Block>
    </AddressABC>
  </DataABC>
</Root>

任何人都可以帮助我告诉我我的错误。

由于

2 个答案:

答案 0 :(得分:1)

就像使用Body/Name获取名称一样,您可以使用Body/Address/City来获取城市(因为上下文项是Document元素)。

但是,您的代码有点单一。在地址元素上执行xsl:apply-templates可能会更好,然后使用match="Address"执行模板规则,您可以使用select="City"选择相对于{{1}的City }}

答案 1 :(得分:1)

迈克尔凯的回答中已经指出了你的错误。

我想建议一种替代方法 - 一种需要少量工作的方法:

XSLT 1.0

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

<xsl:variable name="DocumentType" select="/Document/Type" />

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

<xsl:template match="/Document">
    <Root>
        <xsl:apply-templates select="Header | Body"/>
    </Root>
</xsl:template>

<xsl:template match="Body">
    <xsl:element name="Data{$DocumentType}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="Date | Time">
    <xsl:element name="{name()}Created">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="Address">
    <xsl:element name="Address{$DocumentType}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

请注意,可以从任何模板访问全局变量,并且不需要将其作为参数发送。