复制后更改属性值
Changing an attribute value after copy
给定以下 XML 示例文件:
<root>
<list number="123">
<element>
<name value="Name1"/>
<line value="Line 1 :"/>
</element>
<element>
<name value="Name1"/>
<line value="Line 1 :"/>
</element>
</list>
</root>
我想创建一个 XSL 文件,允许我用 Line 1 : 123
替换每次出现的 Line 1 :
,123
来自 list
节点的属性,number
.
我有以下 XSL 文件:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="element">
<xsl:copy-of select="."/>
<xsl:if test="@value='Line 1 :'">
<xsl:attribute name="type">
<xsl:value-of select="root/list[@number]"/>
</xsl:attribute>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
但是转换失败并且 returns 类似于 "Attributes and namespaces nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added"。
知道这个 XSL 有什么问题吗?
实际上,您收到的错误消息:
Attributes and namespaces nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added
已经很好地解释了问题。您的模板匹配 element
看起来像这样
<xsl:template match="element">
<xsl:copy-of select="."/>
<xsl:if test="@value='Line 1 :'">
<xsl:attribute name="type">
里面的第一条指令:
<xsl:copy-of select="."/>
复制 element
元素及其 所有内容 。这包括子元素、文本节点、属性等。
XSLT的规则之一是,一旦元素节点中添加了某些类型的节点,就不能添加更多的属性节点。但这正是你想要做的
<xsl:attribute name="type">
构造属性节点
您实际上不需要 xsl:copy-of
element
元素的全部内容,因为您有一个身份模板,默认情况下无论如何都会复制所有内容。
只在您想要改变的确切位置进行干预。在这种情况下,它是 line
元素的 value
属性 - 所以编写一个完全匹配的模板。
我认为您需要的是以下内容。如果不是,请 显示 您期望的 XML 输出而不是描述它。我假设可能有多个 list
元素具有不同的 number
属性。
XSLT 样式表
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="element/line/@value">
<xsl:attribute name="value">
<xsl:value-of select="concat(., ' ', ../../../@number)"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
XML输出
<?xml version="1.0" encoding="utf-8"?>
<root>
<list number="123">
<element>
<name value="Name1"/>
<line value="Line 1 : 123"/>
</element>
<element>
<name value="Name1"/>
<line value="Line 1 : 123"/>
</element>
</list>
</root>
编辑
A more concise requirement would be : given any XML file, how can I concatenate any attribute value inside that is equal to "Line 1 :" with the 123 from the number above ? I assume that would need more than one template...
不,这只是一个小的修改。将第二个模板更改为:
<xsl:template match="list//@*[. = 'Line 1 :']">
<xsl:attribute name="{name()}">
<xsl:value-of select="concat(., ' ', ancestor::list[1]/@number)"/>
</xsl:attribute>
</xsl:template>
给定以下 XML 示例文件:
<root>
<list number="123">
<element>
<name value="Name1"/>
<line value="Line 1 :"/>
</element>
<element>
<name value="Name1"/>
<line value="Line 1 :"/>
</element>
</list>
</root>
我想创建一个 XSL 文件,允许我用 Line 1 : 123
替换每次出现的 Line 1 :
,123
来自 list
节点的属性,number
.
我有以下 XSL 文件:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="element">
<xsl:copy-of select="."/>
<xsl:if test="@value='Line 1 :'">
<xsl:attribute name="type">
<xsl:value-of select="root/list[@number]"/>
</xsl:attribute>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
但是转换失败并且 returns 类似于 "Attributes and namespaces nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added"。
知道这个 XSL 有什么问题吗?
实际上,您收到的错误消息:
Attributes and namespaces nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added
已经很好地解释了问题。您的模板匹配 element
看起来像这样
<xsl:template match="element">
<xsl:copy-of select="."/>
<xsl:if test="@value='Line 1 :'">
<xsl:attribute name="type">
里面的第一条指令:
<xsl:copy-of select="."/>
复制 element
元素及其 所有内容 。这包括子元素、文本节点、属性等。
XSLT的规则之一是,一旦元素节点中添加了某些类型的节点,就不能添加更多的属性节点。但这正是你想要做的
<xsl:attribute name="type">
构造属性节点
您实际上不需要 xsl:copy-of
element
元素的全部内容,因为您有一个身份模板,默认情况下无论如何都会复制所有内容。
只在您想要改变的确切位置进行干预。在这种情况下,它是 line
元素的 value
属性 - 所以编写一个完全匹配的模板。
我认为您需要的是以下内容。如果不是,请 显示 您期望的 XML 输出而不是描述它。我假设可能有多个 list
元素具有不同的 number
属性。
XSLT 样式表
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="element/line/@value">
<xsl:attribute name="value">
<xsl:value-of select="concat(., ' ', ../../../@number)"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
XML输出
<?xml version="1.0" encoding="utf-8"?>
<root>
<list number="123">
<element>
<name value="Name1"/>
<line value="Line 1 : 123"/>
</element>
<element>
<name value="Name1"/>
<line value="Line 1 : 123"/>
</element>
</list>
</root>
编辑
A more concise requirement would be : given any XML file, how can I concatenate any attribute value inside that is equal to "Line 1 :" with the 123 from the number above ? I assume that would need more than one template...
不,这只是一个小的修改。将第二个模板更改为:
<xsl:template match="list//@*[. = 'Line 1 :']">
<xsl:attribute name="{name()}">
<xsl:value-of select="concat(., ' ', ancestor::list[1]/@number)"/>
</xsl:attribute>
</xsl:template>