我的意思是当且仅当该属性的数据源存在时才向节点添加属性元素。
换句话说,如果源与我的规则不匹配,我不想以空属性结束。
<tok id="t1" fooID=""/> //not accepted
<tok id="t1" /> //instead of ^
<tok id="t1" fooID="bar"/> //accepted
<小时/> 此外,我想测试源是否有超过1个节点对应于我当前的属性,如果是,则添加另一个
foo
属性和“source2”。以下是我目前正在使用的内容:
<xsl:template match="tokens/token">
<tok id="{@ID}"
ctag="{/root/myStuff/fooSources[1and2 how?]/fooSource[@fooID=current()/@ID]}"
>
</tok>
源XML是这样的:
<root>
<myStuff>
<tokens>
<token ID="bar"/>
<token ID="anotherBar"/>
<token ID="noFoo"/>
</tokens>
<fooSources>
<fooSource fooID="bar"> kitten </fooSource>
<fooSource fooID="anotherBar"> shovel </fooSource>
</fooSources>
<fooSources>
<fooSource fooID="bar"> kitty </fooSource>
<fooSource fooID="notAnotherBar"> fridge </fooSource>
</fooSources>
</myStuff>
</root>
期望的结果是:
<tok id="bar" fooID="kitten" fooID_2="kitty"/>
<tok id="anotherBar" fooID="shovel"/>
<tok id="noFoo" />
提前感谢您的帮助!
PS:我想在xpath 1.0
中这样做答案 0 :(得分:5)
<foo>
<xsl:if test="@bar">
<xsl:attribute name="id">
<xsl:value-of select="@bar"/>
</xsl:attribute>
</xsl:if>
</foo>
答案 1 :(得分:3)
PS:我想在xpath 1.0
中这样做
XPath是XML文档的查询语言,因此无法修改文档的任何节点。
要生成所需结果(更改元素名称并向元素添加新属性),您必须使用托管XPath的另一种语言。最合适的这种语言,特别是为了用于XML转换的目标而创建的是XSLT。
此XSLT 1.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:key name="kFooIdByVal" match="fooSource/@fooID"
use="."/>
<xsl:template match="token">
<tok>
<xsl:copy-of select="@*"/>
<xsl:apply-templates
select="key('kFooIdByVal',@ID)"/>
</tok>
</xsl:template>
<xsl:template match="@fooID">
<xsl:variable name="vattrName"
select="concat('fooID',
substring(concat('_',position()),
1 div (position() >1)
)
)
"/>
<xsl:attribute name="{$vattrName}">
<xsl:value-of select="normalize-space(..)"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="fooSources"/>
</xsl:stylesheet>
应用于提供的XML文档:
<root>
<myStuff>
<tokens>
<token ID="bar"/>
<token ID="anotherBar"/>
<token ID="noFoo"/>
</tokens>
<fooSources>
<fooSource fooID="bar"> kitten </fooSource>
<fooSource fooID="anotherBar"> shovel </fooSource>
</fooSources>
<fooSources>
<fooSource fooID="bar"> kitty </fooSource>
<fooSource fooID="notAnotherBar"> fridge </fooSource>
</fooSources>
</myStuff>
</root>
生成想要的正确结果:
<tok ID="bar" fooID="kitten" fooID_2="kitty"/>
<tok ID="anotherBar" fooID="shovel"/>
<tok ID="noFoo"/>
<强>解释强>:
匹配任何token
元素的模板会创建tok element that has all the existing attributes (if any) of the matched
令牌element. It also applies templates on any
fooID attribute, whose value is the same as the value of the
ID attribute of the current (matched) node. If there isn't any such
fooID属性,没有进一步处理,也没有创建其他属性。
与fooID
属性相匹配的模板必须生成"fooID_{N}"
形式的新属性,其中N
是当前节点的位置(节点列表中匹配的fooID
属性)(由<xsl:apply-templates>
指令创建,该指令选择此当前模板以应用此fooID
属性)。如果N为1,我们不会在名称的开头("fooID"
)附加字符串"_"{N}
。
为了避免默认XSLT处理的副作用,我们添加了一个匹配任何fooSources
元素的第三个模板,并且(模板)有一个空体。