0

我有看起来像这样的 XML。它是外部提供的,不能更改:

<locations>
  <country iso_code="CA">
    <name>Canada</name>
    <state abbreviation="AB">
      <name>Alberta</name>
      <city>
        <name>Leduc</name>
        <location id="1"/>
      </city>
    </state>
    <state abbreviation="BC">
      <name>British Columbia</name>
      <city>
        <name>Abbotsford</name>
        <location id="2"/>
        <location id="3"/>
      </city>
    </state>
    </country>
  <country iso_code="US">
    <name>United States</name>
    <state abbreviation="AZ">
      <name>Arizona</name>
      <city>
        <name >Wikiup</name>
        <location id="1"/>
      </city>
    </state>
  </country>
</locations>

我的 XSL 看起来像这样:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="iso-8859-1"/>
<xsl:strip-space elements="*" />
  <xsl:template match="/">
    <xsl:for-each select="//location[@id]">
      <xsl:call-template name="location"/>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="location">
    <xsl:value-of select="@id"/>,
    <xsl:value-of select="ancestor::city[1]"/>,
    <xsl:value-of select="ancestor::state[1]"/>,
    <xsl:value-of select="ancestor::state[1]/@abbreviation"/>,
    <xsl:value-of select="ancestor::country[1]"/>,
    <xsl:value-of select="ancestor::country[1]/@iso_code"/>,
  </xsl:template>

</xsl:stylesheet>

当我运行 xsltproc 时,我得到了这个输出(我去掉了额外的行以使其更小):

1,Leduc,AlbertaLeduc,AB,CanadaAlbertaLeducBritish ColumbiaAbbotsford,CA,
2,Abbotsford,British ColumbiaAbbotsford,BC,CanadaAlbertaLeducBritish ColumbiaAbbotsford,CA,
3,Abbotsford,British ColumbiaAbbotsford,BC,CanadaAlbertaLeducBritish ColumbiaAbbotsford,CA,
...etc...

问题是当我执行祖先 [1]:: 时,它会提取所有祖先的值,而不仅仅是我正在寻找的那个。

以下是输出的样子:

1,Leduc,Alberta,AB,Canada,CA,
2,Abbotsford,British Columbia,BC,Canada,CA,
3,Abbotsford,British Columbia,BC,Canada,CA,
...etc...

我尝试使用../../。符号并得到相同的结果。我使用了其他一些符号,但它要么不起作用,要么我再次得到这些连接的值。

如何仅获取我正在处理的节点的直接父级的值,而不是该级别的所有节点?

希望我在这里使用正确的术语。这是我第一次将 XSL 用于一次性项目。

店里的网民也被难住了。他们不经常使用 XSL。

4

1 回答 1

1

如果您将 XML 视为盒子,<value-of>则解开选定的盒子及其在其中找到的所有盒子,将它们扔掉并留下盒子中的实际内容。这些是文本节点。属性也被丢弃了,它们是粘在盒子上的标签。

在 的情况下<value-of select="ancestor::state">,它打开<state>盒子并在里面找到两个盒子,一个<name>盒子和一个<city>盒子。因为您使用<strip-space elements="*">它也会丢弃所有空白“气泡包装”,否则它会保留。它继续拆箱,在盒子里找到“Alberta”,<name>盒子里还有两个<city>盒子:A<name>和一个<location>盒子。

于是游戏继续:在刚刚拆箱的<name>盒子里,它找到Leduc并把它放在旁边,但它在盒子Alberta里什么也没找到。<location>现在,没有什么要解压的了。所以我们剩下一堆纸板和泡沫包装垃圾,以及实际的内容,即AlbertaLeduc(粘合在一起AlbertaLeduc)。

这是您的代码的建议改进:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" encoding="iso-8859-1"/>
  <xsl:strip-space elements="*" />

  <xsl:template match="/">
    <xsl:apply-templates select="//location[@id]"/>
  </xsl:template>

  <xsl:template match="location">
    <xsl:value-of select="@id"/>,
    <xsl:value-of select="ancestor::city[1]/name"/>,
    <xsl:value-of select="ancestor::state[1]/name"/>,
    <xsl:value-of select="ancestor::state[1]/@abbreviation"/>,
    <xsl:value-of select="ancestor::country[1]/name"/>,
    <xsl:value-of select="ancestor::country[1]/@iso_code"/>,
  </xsl:template>

</xsl:stylesheet>
于 2013-10-07T19:42:54.663 回答