仅当源属性存在时,XSLT 才向节点添加属性
我的意思是,当且仅当该属性的数据源存在时,才将属性元素添加到节点。
换句话说,我不想最终得到空属性,以防源与我的规则不匹配。
<tok id="t1" fooID=""/> //not accepted
<tok id="t1" /> //instead of ^
<tok id="t1" fooID="bar"/> //accepted
Moreover, I would like to test if the source has more than 1 node corresponding to my current attribute, and if so, add another
foo
attribute with "source2". Here's what I'm currently using:<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 中执行此操作
I mean to add an attribute element to a node if and only if the source for that attribute's data exists.
In other words, I don't want to end up with empty attributes in case the source isn't matched by my rule.
<tok id="t1" fooID=""/> //not accepted
<tok id="t1" /> //instead of ^
<tok id="t1" fooID="bar"/> //accepted
Moreover, I would like to test if the source has more than 1 node corresponding to my current attribute, and if so, add another
foo
attribute with "source2". Here's what I'm currently using:<xsl:template match="tokens/token">
<tok id="{@ID}"
ctag="{/root/myStuff/fooSources[1and2 how?]/fooSource[@fooID=current()/@ID]}"
>
</tok>
The source XML is like this:
<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>
The desired result would be this:
<tok id="bar" fooID="kitten" fooID_2="kitty"/>
<tok id="anotherBar" fooID="shovel"/>
<tok id="noFoo" />
Thanks in advance for any help!
PS: I'd like to do this in xpath 1.0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
XPath 是 XML 文档的查询语言,因此它不能修改文档的任何节点。
产生想要的结果(更改元素名称并添加元素的新属性)您必须使用另一种托管 XPath 的语言。最合适的此类语言是 XSLT,它是专门为用于 XML 转换而创建的。
此 XSLT 1.0 转换:
应用于提供的 XML 文档时:
产生所需的正确结果:
说明:
匹配任何
token
元素的模板会创建一个tok元素,该元素具有匹配的
token的所有现有属性(如果有)元素。它还将模板应用于任何
fooID属性,其值与当前(匹配)节点的
ID属性值相同。如果没有任何此类
fooID` 属性,则不会进行进一步处理,也不会创建其他属性。与
fooID
属性匹配的模板必须生成"fooID_{N}"
形式的新属性,其中N
是当前节点(匹配的fooID
属性)在节点列表(由
指令创建)中的位置,选择了当前模板以应用于此fooID
属性)。如果 N 为 1,我们不会在名称 ("fooID"
) 的开头附加字符串"_"{N}
。为了避免默认 XSLT 处理的副作用,我们添加了与任何
fooSources
元素匹配的第三个模板,并且(该模板)具有空正文。XPath is a query language for XML documents and as such it cannot modify any nodes of the document.
To produce the wanted result (changing element names and adding new attributes to elements) you have to use another language that is hosting XPath. The most appropriate such language, created especially with the goal to be used for XML transformations is XSLT.
This XSLT 1.0 transformation:
when applied on the provided XML document:
produces the wanted, correct result:
Explanation:
A template matching any
token
element creates atok element that has all the existing attributes (if any) of the matched
tokenelement. It also applies templates on any
fooIDattribute, whose value is the same as the value of the
IDattribute of the current (matched) node. If there isn't any such
fooID` attribute, no futher processing is done and no additional attributes are created.The template that matches a
fooID
attribute must generate a new attribute of the form"fooID_{N}"
whereN
is the position of the current node (the matchedfooID
attribute) in the node-list (created by the<xsl:apply-templates>
instruction that selected this current template for applying on thisfooID
attribute). If N is 1, we do not append to the start of the name ("fooID"
) the string"_"{N}
.To avoid the side-effects of default XSLT processing we add a third template that matches any
fooSources
element and, (the template) has an empty body.