我正在使用仅支持 xsl 1.0 的 xmlstarlet 将一个 xml 转换为另一个。
我正在尝试查找属性“atr1”的值,并在同一节点中插入另一个属性“atr2”。
当使用下面的sample.xml时
<a>
<b></b>
<c>
<d atr1="#{not MGR_1}" atr2="#{condition1}"></d>
<d atr1="#{ MGR_2}" ></d>
<d atr1="2"></d>
</c>
</a>
使用以下transform.xsl
<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="d[contains(@atr1, 'MGR_')]">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:attribute name="atr2">
<xsl:choose>
<xsl:when test="@atr2">
<xsl:value-of select="concat('#{', substring(@atr2,3,string-length(@atr2)-3), ' and not ', substring(@atr1,3))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('#{not ', substring(@atr1,3))" />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我得到的预期o/p如下。
<a>
<b/>
<c>
<d atr1="#{not MGR_1}" atr2="#{condition1 and not not MGR_1}"/>
<d atr1="#{ MGR_2}" atr2="#{not MGR_2}"/>
<d atr1="2"/>
</c>
</a>
但是当我尝试使用下面的 xml 时。其中还有另一个内部元素x,那么问题就出现了。
<a>
<b></b>
<c>
<d atr1="#{not MGR_1}" atr2="#{condition1}"></d>
<d atr1="#{ MGR_2}" ></d>
<d atr1="2"></d>
<d atr1="#{ MGR_3}" >
<x>blah blah blah</x>
</d>
</c>
</a>
尝试转换上述 XML。我收到一条错误消息:
$ xml tr transform.xsl sample.xml
runtime error: file transform.xsl line 14 element attribute
xsl:attribute: Cannot add attributes to an element if children have been already added to the element.
我哪里理解错了。在修改后的 XML 上获得所需的 O/P 的正确 XSL 可能是什么。
最佳答案
您收到的错误消息实际上是不言而喻的。如果子节点已分配给节点,则无法添加属性。
只需将模板应用于所有属性 @*
与将模板应用于所有潜在子节点 node()
分开即可。请注意,这不仅捕获子元素。
顺便说一句,我只能使用 Saxon 9.5.1 重现您的错误消息,但不能使用 Saxon 6.5.5 和 Xalan 2.7.1。
样式表
<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="d[contains(@atr1, 'MGR_')]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="atr2">
<xsl:choose>
<xsl:when test="@atr2">
<xsl:value-of select="concat('#{', substring(@atr2,3,string-length(@atr2)-3), ' and not ', substring(@atr1,3))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('#{not ', substring(@atr1,3))" />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
关于xml - 使用 xsl 1.0 将 xml 转换为 xml 时。 xsl :attribute: Cannot add attributes to an element if children have been already added to the element,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21984867/