XSLT仅当源属性存在时才向节点添加属性
我的意思是,当且仅当属性数据的源存在时,才向节点添加属性元素 换句话说,我不想以空属性结束,以防源与我的规则不匹配XSLT仅当源属性存在时才向节点添加属性,xslt,xpath,attributes,Xslt,Xpath,Attributes,我的意思是,当且仅当属性数据的源存在时,才向节点添加属性元素 换句话说,我不想以空属性结束,以防源与我的规则不匹配 <tok id="t1" fooID=""/> //not accepted <tok id="t1" /> //instead of ^ <tok id="t1" fooID="bar"/> //accepted 源XML如下所示: <root> <myStuff> <tokens>
<tok id="t1" fooID=""/> //not accepted
<tok id="t1" /> //instead of ^
<tok id="t1" fooID="bar"/> //accepted
源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:我想在XPath1.0中实现这一点
PS:我想在XPath1.0中实现这一点
XPath是XML文档的查询语言,因此它不能修改文档的任何节点。
要产生想要的结果(更改元素名称并向元素添加新属性),必须使用承载XPath的另一种语言。最合适的此类语言是XSLT,特别是为了用于XML转换而创建的
此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>
<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"/>
应用于提供的XML文档时:
<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>
<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"/>
小猫
铲子
基蒂
冰箱
生成所需的正确结果:
<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>
<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"/>
说明:
<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>
<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"/>
标记元素的模板将创建一个tok元素,该元素具有匹配的标记元素的所有现有属性(如果有)。它还将模板应用于任何
fooID属性,其值与当前(匹配)节点的
ID属性的值相同。如果没有任何此类
fooID`属性,则不会进行进一步的处理,也不会创建其他属性
fooID
属性的模板必须生成一个新属性,其形式为“fooID{N}”
,其中N
是当前节点(匹配的fooID
属性)在节点列表中的位置(由选择此当前模板以应用于此fooID
属性的
指令创建)。如果N为1,我们不会在名称(“fooID”
)的开头追加字符串“{N}
fooSources
元素,并且(模板)有一个空的主体
好问题,+1。完整、简短、简单的XSLT 1.0解决方案见我的答案:)很漂亮。谢谢我实际上是想说XSLT而不是xpath,把它们搞混了……嗯,尽管在firefox中测试时一切都正常,但从使用Saxon 9.2的java程序调用时,`don show/work'返回的值似乎根本不起作用。。。知道为什么会这样吗?(没有错误,就好像没有匹配的值)@Twodordan:Java程序中的某个东西。。。此转换首先在Saxon上运行,然后在其他XSLT处理器上运行。。。所有这些都会产生相同的正确结果。@Dimitre你是对的。问题是(现在仍然是)我正在以web服务的形式运行我的程序。ApacheTomcat服务器(localhost)根本没有使用Saxon。必须弄清楚如何让它使用saxon9.jar。。。一直以来,我都以为我在使用saxon,但我不是Twodordan:转换是标准的XSLT1.0,任何兼容的XSLT1.0处理器(不仅仅是saxon)都会毫无问题地执行它。