我正在尝试编写XSLT以将XML从一种格式转换为另一种格式。当我将.xslt
文件应用于VS 2010中的XML文件时,创建了输出XML结构,没有任何问题。但它并未填写处理xsl:value-of
预期的数据。
当我使用XMLSpy
并评估XPath
表达式时,对于以下XSLT中的表达式,它会显示no result
。但是当我在XPath表达式的末尾使用node()
函数时,它会显示值!
node()
和text()
种函数?如果不是,为什么XmlSpy也没有给出没有这些函数的结果?我开始关注w3school tutorial。我是XSLT的新手。
这是我想要转换为其他XML格式的XML。
<ServiceMessage xmlns="http://requestservice/requests" xmlns:req="http://requestservice/requests/xmlstds">
<TypeOfReq> General </TypeOfReq>
<Details>
<Id> 123456789 </Id>
<SenderDetails>
<Sender id="345"></Sender>
</SenderDetails>
</Details>
</ServiceMessage>
这是我的XSLT
<?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="/">
<request>
<requestType>
<xsl:value-of select="ServiceMessage/TypeOfReq" />
</requestType>
<Id>
<xsl:value-of select="ServiceMessage/Details/Id"/>
</Id>
<senderId>
<xsl:value-of select="ServiceMessage/Details/SenderDetails/Sender/@id"/>
</senderId>
</request>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:2)
您已从合成的角度正确编写了xpath。您实际遇到的问题实际上与名称空间有关。在XML中,您指定了一个默认命名空间
<ServiceMessage xmlns="http://requestservice/requests">
这意味着除非另有说明,否则所有子元素都属于该命名空间。但是,在您的XSLT中,根本没有对此namepsace的引用,因此XSLT正在查找未指定命名空间的元素。您的XML不是这种情况。
对于XSLT 1.0,您需要声明命名空间,如下所示:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://requestservice/requests">
然后,您将明确说明它用于匹配元素的位置
<xsl:value-of select="s:ServiceMessage/s:TypeOfReq" />
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://requestservice/requests">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<request>
<requestType>
<xsl:value-of select="s:ServiceMessage/s:TypeOfReq"/>
</requestType>
<Id>
<xsl:value-of select="s:ServiceMessage/s:Details/s:Id"/>
</Id>
<senderId>
<xsl:value-of select="s:ServiceMessage/s:Details/s:SenderDetails/s:Sender/@id"/>
</senderId>
</request>
</xsl:template>
</xsl:stylesheet>
应用于XML时,输出以下内容
<request xmlns:s="http://requestservice/requests">
<requestType> General </requestType>
<Id> 123456789 </Id>
<senderId>345</senderId>
</request>
请注意,这里字母's'的选择纯粹是武断的,它可能是真的。
答案 1 :(得分:0)
回答第3个问题“如何摆脱内置模板?”
如果您没有为xml中出现的元素指定模板,在您的情况下,VS将应用身份模板,这只会将源元素复制到您的输出。
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
有关详细信息,请参阅Microsoft's explanation on built in templates。
(atm我不知道是否可以关闭它,因为我这里只有VS Express,它不提供Xslt调试)
作为一般规则,您应始终为要处理的所有元素指定模板,因此您的基本xslt始终以
开头<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://requestservice/requests">
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
</xsl:stylesheet>
接下来,在您的情况下,为根元素添加模板 ServiceMessage
<xsl:template match="s:ServiceMessage">
<!-- usually apply-templates, in your case create new output element(s) -->
<xsl:template>