XSLT 访问和创建嵌套 xml 并将标签转换为属性
XSLT to access and create nested xml and convert tags to attributes
我在下面输入 XML 消息,需要将其转换为具有多个属性的嵌套 XML。
<S1>
<P>23432</P>
<Su>BG</Su>
<S2>
<P>cc</P>
<Su>B</Su>
<S3>
<P>427013947</P>
<Su>RM</Su>
<F>MDF</F>
<I>427113948</I>
<C>true</C>
<T></T>
<A>xxx</A>
</S3>
<F></F>
<I>427013947</I>
<C>true</C>
<T></T>
<A>xxxsx</A>
</S2>
<S2>
<P>cc</P>
<Su>FL</Su>
<F>1</F>
<I>427814536</I>
<C>true</C>
<T></T>
<A>xxxsx</A>
</S2>
<S2>
<P>cc</P>
<Su>G</Su>
<F></F>
<I>444</I>
<C>true</C>
<T></T>
<A>xxxsx</A>
</S2>
<F>1</F>
<I>cc</I>
<C>true</C>
<T></T>
<A>xxxs</A>
<B></B>
</S1>
输出XML
<S1 P="23432" Su="BG" F="1" I="cc" C="true" T="" A="xxxs" B="">
<S2 P="cc" Su="B" F="" I="427013947" C="true" T="" A="xxxsx">
<S3 P="427013947" Su="RM" F="MDF" I="427113948" C="true" T="" A="xxx"></S3>
</S2>
<S2 P="cc" Su="FL" F="1" I="427814536" C="true" T="" A="xxxsx"></S2>
<S2 P="cc" Su="G" F="" I="444" C="true" T="" A="xxxsx"></S2>
</S1>
所有 S1、S2、S3 标签应保持原样,而其他子标签应作为属性添加到各自的父标签。嵌套 XML 数组的深度增加到 9,如 S1、S2、S3 ...S9。
我尝试编写 XSLT 转换并尝试使用递归函数,但我无法做到。有人可以帮我写一个 XSLT sheet 来做这个转换吗?
我尝试了类似下面的方法(未完成),实现此目的的最佳方法是什么?解决方案应该在 XSLT 1.0 中。
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="//S1">
<xsl:element name="S1">
<xsl:for-each select="*">
<xsl:if test="local-name()!='S1'">
<xsl:attribute name="{name()}" >
<xsl:value-of select="text()" />
</xsl:attribute>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="S2">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:for-each>
</xsl:element>
</xsl:template></xsl:stylesheet>
如果您仅限于 XSLT 1.0,那么这会很尴尬,因为需要区分 Su
和 S3
。
但是,如果可以假设任何(且唯一)没有子元素的元素应该转换为属性,那么这可以简单而优雅地完成:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="*[*]">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]"/>
<xsl:apply-templates select="*[*]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*)]">
<xsl:attribute name="{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
我在下面输入 XML 消息,需要将其转换为具有多个属性的嵌套 XML。
<S1>
<P>23432</P>
<Su>BG</Su>
<S2>
<P>cc</P>
<Su>B</Su>
<S3>
<P>427013947</P>
<Su>RM</Su>
<F>MDF</F>
<I>427113948</I>
<C>true</C>
<T></T>
<A>xxx</A>
</S3>
<F></F>
<I>427013947</I>
<C>true</C>
<T></T>
<A>xxxsx</A>
</S2>
<S2>
<P>cc</P>
<Su>FL</Su>
<F>1</F>
<I>427814536</I>
<C>true</C>
<T></T>
<A>xxxsx</A>
</S2>
<S2>
<P>cc</P>
<Su>G</Su>
<F></F>
<I>444</I>
<C>true</C>
<T></T>
<A>xxxsx</A>
</S2>
<F>1</F>
<I>cc</I>
<C>true</C>
<T></T>
<A>xxxs</A>
<B></B>
</S1>
输出XML
<S1 P="23432" Su="BG" F="1" I="cc" C="true" T="" A="xxxs" B="">
<S2 P="cc" Su="B" F="" I="427013947" C="true" T="" A="xxxsx">
<S3 P="427013947" Su="RM" F="MDF" I="427113948" C="true" T="" A="xxx"></S3>
</S2>
<S2 P="cc" Su="FL" F="1" I="427814536" C="true" T="" A="xxxsx"></S2>
<S2 P="cc" Su="G" F="" I="444" C="true" T="" A="xxxsx"></S2>
</S1>
所有 S1、S2、S3 标签应保持原样,而其他子标签应作为属性添加到各自的父标签。嵌套 XML 数组的深度增加到 9,如 S1、S2、S3 ...S9。
我尝试编写 XSLT 转换并尝试使用递归函数,但我无法做到。有人可以帮我写一个 XSLT sheet 来做这个转换吗?
我尝试了类似下面的方法(未完成),实现此目的的最佳方法是什么?解决方案应该在 XSLT 1.0 中。
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="UTF-8" />
<xsl:template match="//S1">
<xsl:element name="S1">
<xsl:for-each select="*">
<xsl:if test="local-name()!='S1'">
<xsl:attribute name="{name()}" >
<xsl:value-of select="text()" />
</xsl:attribute>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="S2">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:for-each>
</xsl:element>
</xsl:template></xsl:stylesheet>
如果您仅限于 XSLT 1.0,那么这会很尴尬,因为需要区分 Su
和 S3
。
但是,如果可以假设任何(且唯一)没有子元素的元素应该转换为属性,那么这可以简单而优雅地完成:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="*[*]">
<xsl:copy>
<xsl:apply-templates select="*[not(*)]"/>
<xsl:apply-templates select="*[*]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*)]">
<xsl:attribute name="{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>