通过XSL修改XML属性时Terraform报xdr解码错误如何排查
问题描述
现有XML片段如下:
</disk> <disk type='file' device='cdrom'> <driver name='qemu' type='raw'/> <source file='discovery.iso' index='1'/> <backingStore/> <target dev='hdd' bus='ide'/> <readonly/> <alias name='ide0-1-1'/> <address type='drive' controller='0' bus='1' target='0' unit='1'/> </disk>
需求为将XML中target节点的bus属性值从ide修改为scsi。
使用的XSL转换模板运行时抛出异常,模板内容如下:
<?xml version="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:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="disk[@type='file']/target"> <xsl:copy> <xsl:attribute name="bus">scsi</xsl:attribute> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
Terraform运行时错误信息:
xdr:DecodeUint: EOF while decoding 4 bytes - read
错误原因
XSL模板存在核心逻辑错误:
自定义target节点匹配模板时,先手动创建了值为scsi的bus属性,后续执行<xsl:apply-templates select="@*|node()"/>时又将原节点自带的bus="ide"属性复制到目标节点,最终生成的target节点存在两个同名bus属性,属于非法XML结构。Terraform的libvirt provider底层依赖libvirt解析XML,遇到非法结构时就会抛出这类EOF解码错误。
另外提供的XML片段开头存在孤立的</disk>闭合标签,如果是实际使用的XML内容,需要先删除该无效标签,保证XML本身格式合法。
修正方法
调整target节点的模板逻辑,复制原属性时排除原有bus属性即可,修正后的完整XSL如下:
<?xml version="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:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="disk[@type='file']/target"> <xsl:copy> <!-- 写入修改后的bus属性 --> <xsl:attribute name="bus">scsi</xsl:attribute> <!-- 复制除原有bus属性外的其他所有属性、子节点 --> <xsl:apply-templates select="@*[name()!='bus']|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
转换后生成的target节点符合规范,结构如下:
<target dev='hdd' bus='scsi'/>
内容的提问来源于stack exchange,提问作者RasedPegasus69
相关产品推荐
相关产品推荐

