嗨,我有一个xml文件,如下所示:
<root>
<body>
<place attr="1" id="1" ref="www.example.com">
<name>abc
</name>
</place>
<place attr="1" id="2" ref="www.example.com">
<name>def
</name>
</place>
<place attr="2" id="3">
<place attr="3" id="4" ref="www.example.com">
<name>efg
</name>
</place>
</place>
</body>
</root>
我想获取所有具有子元素<place>
且元素之间没有文本的元素<name>
。
我想要的输出是这样的:
<root>
<place attr="1" id="1" ref="www.example.com" />
<place attr="1" id="2" ref="www.example.com" />
<place attr="3" id="4" ref="www.example.com" />
</root>
我的xsl代码返回所有<place>
标签(我不想要)+ <name>
标签之间的文本:
<xsl:template match="root">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="place">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
xml输出:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<place attr="1" id="1" ref="www.example.com">abc</place>
<place attr="1" id="2" ref="www.example.com">def</place>
<place attr="2" id="3">
<place attr="3" id="4" ref="www.example.com">efg</place>
</place>
</root>
答案 0 :(得分:1)
关键是您的apply-templates
语句。
如您所述,您“只想要<place>
标签,并且在孩童时期拥有<name>
” 。因此,您应该只选择那些。
您当前的代码:
<xsl:template match="root">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
仅使用<xsl:apply-templates/>
时,这与说“将模板应用于此下的 *一切* ”相同。因此,您甚至可以捕获甚至不需要的那些<place>
元素。
为了更具选择性并得到您想要的,我们可以说:
<xsl:apply-templates select="descendant::place[name]"/>
我们使用select
语句进行选择。 :)我们不想将模板应用于所有,而仅应用于特定事物,这就是我们指定哪些事物的方式。
我们使用descendant::
轴是因为我们想捕获<place>
元素中包含的所有<root>
元素。如果我们只说select="place[name]"
,则意味着“仅将模板应用于这些<place>
元素的直接子元素<root>
。因为没有<place>
元素是此<root>
元素的直接子元素,对您没有任何帮助。
我们使用[name]
谓词来指定条件,即我们只希望具有<place>
个子元素的<name>
个元素。这样一来,我们就排除了<place attr="2" id="3">
,后者包含另一个<place>
,但没有自己的任何<name>
子代。
我希望这会有所帮助。如果您有任何您不了解的地方,请发表评论。
我错误地估计了较早答案中要包含的详细信息。 :)
这是一个带有注释的完整示例。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<!-- Start at the logical root / since every XSLT *must* start there. -->
<xsl:template match="/">
<!-- We just pass everything along. NOTE: We NEED to define templates
for anything special we want to do, beyond just the default
XSLT behavior of outputting the string contents minus any elements. -->
<xsl:apply-templates/>
</xsl:template>
<!-- We want to get the <root> element and attributes in our output, so
we define a template to do that.-->
<xsl:template match="root">
<xsl:copy>
<xsl:copy-of select="@*"/>
<!-- We also want to process the content of <root>, so we use
`xsl:apply-templates`. Since we also want to be _selective_
about what we process, we also specify a `select` statement
with the XPath needed to identify what we want.
Again, we NEEd to define a template to process this,
or we'll just get the text string content and none of
the elements. -->
<xsl:apply-templates select="descendant::place[name]"/>
</xsl:copy>
</xsl:template>
<!-- Here we define what to do with the <place> elements that have
<name> children. Since your <place attr="2" id="3"> element
has no <name> child, it gets omitted from the output. -->
<xsl:template match="place[name]">
<xsl:copy>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:template>
<!-- Lastly, we define one more template that says "capture everything
else, and *don't* output anything". This way, we don't get the text
string output of anything we haven't explicitly defined above. -->
<xsl:template match="*"/>
</xsl:stylesheet>
我们只得到所需的元素,而没有包含它们的文本。
答案 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:template match="/root">
<xsl:copy>
<xsl:for-each select=".//place[name]">
<xsl:copy>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
首先,您需要了解XSLT process model:从输入文档的文档根目录开始,处理器尝试将此节点与某些模板的模式所描述的规则进行匹配。 built-in rules有一些:基本上,它们逐级遍历输入文档,并按文档顺序从头到尾遍历。
这就是为什么您需要一条规则来复制root
和place
元素,以及一条不输出文本节点的规则。
使用此输入
<root>
<body>
<place attr="1" id="1" ref="www.example.com">
<name>abc
</name>
</place>
<place attr="1" id="2" ref="www.example.com">
<name>def
</name>
</place>
<place attr="2" id="3">
<place attr="3" id="4" ref="www.example.com">
<name>efg
</name>
</place>
</place>
</body>
</root>
此样式表
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="root|place[name]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
输出
<root>
<place attr="1" id="1" ref="www.example.com" />
<place attr="1" id="2" ref="www.example.com" />
<place attr="3" id="4" ref="www.example.com" />
</root>