我想用XSL选择并重命名第一个子元素。但它并不是第一个孩子,它更像是第一个孩子的第一个节点。
XML看起来像这样:
<Root><Story>
<CL>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
<CL>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
</Story></Root>
我需要重新命名<name>
之后的第一个<CL>
元素,例如<name1>
,同时保留其他<name>
元素:
<Root><Story>
<CL>
<BK>
<name1>...</name1>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
<CL>
<BK>
<name1>...</name1>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
</Story></Root>
答案 0 :(得分:0)
假设您的问题是关于如何选择正确的元素(而不是在找到它们后如何替换它们),则以下XPath表达式会选择每个元素的第一个子元素中的第一个<name>
元素。 {1}}元素:
<CL>
请注意,在/Root/Story/CL/*[1]/name[1]
下,如何选择任意元素(<CL>
)。此选择仅限于*
的父<CL>
元素中的第一个此类元素。
更新:嵌入到XSLT中,然后可以使用以下模板重命名该元素:
[1]
更新2:限制选择第一个<xsl:template match="/Root/Story/CL/*[1]/name[1]">
<name1><xsl:apply-templates select="node()|@*"/></name1>
</xsl:template>
元素。
答案 1 :(得分:0)
参考您的评论,不,您不应该使用WHEN / OTHERWISE。覆盖模板是最佳选择。
以下XSLT 1.0样式表是对规则的简单解释&#34;我需要重命名后的第一个元素,例如将其他元素保留为&#34;,而不假设任何特定结构输入文件......
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="name[(preceding::name | ancestor::CL)[last()]/self::CL]">
<name1>
<xsl:apply-templates select="@*|node()"/>
</name1>
</xsl:template>
</xsl:stylesheet>
如果您可以使用XSLT 2.0或对输入文档的结构做出某些保证,那么将会有更简单的解决方案。如果其中任何一个条件成立,请更新您的问题。
答案 2 :(得分:0)
这是一个完整而简短的解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BK[1]/name">
<name1>
<xsl:apply-templates select="@*|node()"/>
</name1>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<Root><Story>
<CL>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
<CL>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
</Story></Root>
产生了想要的正确结果:
<Root>
<Story>
<CL>
<BK>
<name1>...</name1>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
<CL>
<BK>
<name1>...</name1>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
<BK>
<name>...</name>
<Address>...</Address>
</BK>
</CL>
</Story>
</Root>
<强>解释强>:
实际需要的是重命名具有name
个孩子的任何元素(在这种情况下只是BK
)的第一个CL
元素的BK
子元素。 / p>
identity rule 复制每个匹配的节点(选择执行该节点)“按原样”。
标识模板被匹配任何name
元素的单个模板覆盖,该元素是{1}元素的子元素,该元素是其父元素的第一个子元素。这里生成一个BK
元素,只需应用模板即可复制其属性和主体(因为它们仅由其他模板匹配和处理 - 身份规则)。