我需要生成一个XML文档,以便与第三方供应商集成。他们的范例是任何字符串元素都被设置为属性,而任何复杂对象都是具有相同规则的单独节点。
我正在尝试使用XSLT将此对象的序列化表示形式转换为基于其.dtd的文档格式。不幸的是,我无法使用[XmlAttribute]装饰这些特定元素,因为它们的值可能为null(我在发送请求之前使用XSLT删除这些节点)。
基本上,我试图在XSLT中弄清楚如何执行以下操作:“对于我的元素的每个子节点,如果该子节点没有子节点,则将该元素转换为元素上的属性。” /强>
我正在使用以下代码片段,我发现它似乎可以满足我的需求:
<!-- Match elements that are parents -->
<xsl:template match="*[*]">
<xsl:choose>
<!-- Only convert children if this element has no attributes -->
<!-- of its own -->
<xsl:when test="not(@*)">
<xsl:copy>
<!-- Convert children to attributes if the child has -->
<!-- no children or attributes and has a unique name -->
<!-- amoung its siblings -->
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="not(*) and not(@*) and
not(preceding-sibling::*[name( ) =
name(current( ))])
and
not(following-sibling::*[name( ) =
name(current( ))])">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
然而,这个错误与:
异常:: System.Xml.Xsl.XslTransformException:属性和 命名空间节点不能在文本后添加到父元素, 已添加comment,pi或子元素节点。
我的XSLT技能有点弱。任何帮助将不胜感激!
有关详情,请说文档如下:
<Root>
<type>Foo</type>
<includeHTML>Yes</includeHTML>
<SubRoot>
<SubSubRoot>
<ID>2.4</ID>
</SubSubRoot>
</SubRoot>
</Root>
我希望结果看起来像这样:
<Root type="foo" includeHTML="Yes">
<SubRoot>
<SubSubRoot ID="2.4" />
</SubRoot>
</Root>
编辑编辑:我只使用.NET 4.5.1,XSLT 1.0。卫生署!
答案 0 :(得分:0)
我不完全确定你在问什么,但我会试一试。
此样式表假定仅包含文本节点的元素被包含为父元素的属性 - 即使文本节点在某种意义上是元素的子元素。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*|*[*]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:choose>
<xsl:when test="*[not(./*) and not(./@*)]">
<xsl:for-each select="*[not(./*) and not(./@*)]">
<xsl:attribute name="{current()/local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
<xsl:apply-templates select="*[*]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(./*) and not(./@*)]"/>
<xsl:template match="@*|text()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于样本输入:
<?xml version="1.0" encoding="utf-8"?>
<root>
<car nr="1">
<color>blue</color>
<speed>210</speed>
</car>
<car nr="2">
<color>red</color>
<speed>100</speed>
</car>
</root>
您会得到以下结果:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<car nr="1" color="blue" speed="210"/>
<car nr="2" color="red" speed="100"/>
</root>
编辑:应用于您的更新输入,我得到:
<?xml version="1.0" encoding="UTF-8"?>
<Root type="Foo" includeHTML="Yes">
<SubRoot>
<SubSubRoot ID="2.4"/>
</SubRoot>
</Root>