xml - 使用 xsl 1.0 将 xml 转换为 xml 时。 xsl :attribute: Cannot add attributes to an element if children have been already added to the element

标签 xml xslt xmlstarlet

我正在使用仅支持 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/

相关文章:

xml - Eclipse 的最佳 XML 编辑器

xml - 根据同一元素的第二个属性的值更改属性的值

xmlstarlet 根据条件选择值

XML - 分组和合并元素,同时保留所有元素文本

php - 用户登录 TWITTER 后获取用户详细信息

java - 如何使用 XML 框架简单生成以下 XML 文件

xml - 解析器与词法分析器和 XML

regex - XSL : how can I generate a regex pattern on demand?

json - 转换没有根名称的 JSON 对象

xmlstarlet 解析器错误 : Entity '*' not defined