我的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。
答案 0 :(得分:1)
如果您将XML视为框,<value-of>
将所选框和它找到的所有框解包,将它们抛弃并留给框中的实际内容。这些是文本节点。属性也被抛弃了,它们是粘在盒子上的一种标签。
如果是<value-of select="ancestor::state">
,则会解压缩<state>
框,并在其中找到两个框,一个<name>
框和一个<city>
框。因为你正在使用<strip-space elements="*">
它也会抛弃所有的白色空间“泡沫包装”,否则它会保留。它会继续取消装箱并在<name>
框中找到“Alberta”,在<city>
框中找到另外两个框:<name>
和<location>
框。
所以游戏继续:在刚刚取消装箱的<name>
框内,找到Leduc
并将其保持在Alberta
旁边,但它在<location>
中找不到任何内容}框。现在,没有什么可以拆包了。所以我们留下了一堆纸板和泡沫包装废物,以及实际内容,Alberta
和Leduc
(粘合在一起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>