这一直是我的头脑。你能帮我吗?! 我有一个简单的xml文件。使用xslt我想将其转换为yaml文件。问题是:
考虑一下:
<data>
<info>some info</info>
<data>some data</data>
<list>
<ofert>
<unknow>....</unknow>
<unknow1>....</unknow1>
<id>00934</id>
<name>Bob</name>
<street>Euston rd.</street>
<postcode>SE23GH</postcode>
<job>IT</job>
<position>boss</position>
<unknow>....</unknow>
<unknow4>....</unknow4>
<unknow2>....</unknow2>
<unknow3>....</unknow3>
</ofert>
</list>
</data>
我想输出如下:
data: info: .... data: .... list: ofert: id: 00934 name: Bob address: {street: Euston rd, postcode: SE23GH } work: {job: IT, position: boss } other: {unknow: ....., unknow1: .... }
答案 0 :(得分:1)
这是一个简单的XSLT 1.0解决方案,不包含'other:'yaml元素......
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*" />
<xsl:template match="*">
<xsl:call-template name="indent">
<xsl:with-param name="spaces" select="count(ancestor::*)"/>
</xsl:call-template>
<xsl:value-of select="concat( local-name(), ': ', text(), '
')"/>
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="ofert">
<xsl:variable name="indent" select="count(ancestor::*)" />
<xsl:call-template name="indent">
<xsl:with-param name="spaces" select="$indent"/>
</xsl:call-template>
<xsl:value-of select="concat( local-name(), ': ', text(), '
')"/>
<xsl:apply-templates select="id" />
<xsl:apply-templates select="name" />
<xsl:call-template name="indent">
<xsl:with-param name="spaces" select="$indent + 1"/>
</xsl:call-template>
<xsl:value-of select="concat(
'address: {street: ', street/text(),
', postcode: ', postcode,' }
')"/>
<xsl:call-template name="indent">
<xsl:with-param name="spaces" select="$indent + 1"/>
</xsl:call-template>
<xsl:value-of select="concat(
'work: {job: ', job,
', position: ', position, ' }
')"/>
</xsl:template>
<xsl:template name="indent">
<xsl:param name="spaces" />
<xsl:if test="$spaces > 0">
<xsl:value-of select="' '"/>
<xsl:call-template name="indent">
<xsl:with-param name="spaces" select="$spaces - 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0解决方案会简单得多。如果您不受XSLT 1.0约束,请告诉我们。
如果我有时间,我会更新解决方案以包含'other:'元素。基本上,该技术只是定义一个命名模板来生成关联数组,如address:,work:和other:,其中输入参数包括缩进级别,标签('地址'等)和关联数组成员列表节点。我希望你明白这一点。
这是XSLT 2.0版本,其中包含“其他”yaml元素......
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:zzart="http://stackoverflow.com/questions/11192960">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="indent-unit" select = "' '" />
<xsl:function name="zzart:indent" as="xs:string">
<xsl:param name="level" as="xs:integer"/>
<xsl:value-of select="fn:string-join( for $in in 1 to $level return $indent-unit, '')" />
</xsl:function>
<xsl:template match="@*" />
<xsl:template match="*">
<xsl:value-of select="concat( zzart:indent( count(ancestor::*)), local-name(), ': ', text(), '
')"/>
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="ofert">
<xsl:variable name="level" select="count(ancestor::*)" />
<xsl:variable name="indent" select="zzart:indent( $level)" />
<xsl:value-of select="concat( $indent, local-name(), ': ', text(), '
')"/>
<xsl:apply-templates select="id" />
<xsl:apply-templates select="name" />
<xsl:call-template name="associative-array">
<xsl:with-param name="level" select="$level + 1" />
<xsl:with-param name="array-name" select="'address'" />
<xsl:with-param name="array-members" select="(street, postcode)" />
</xsl:call-template>
<xsl:call-template name="associative-array">
<xsl:with-param name="level" select="$level + 1" />
<xsl:with-param name="array-name" select="'work'" />
<xsl:with-param name="array-members" select="(job, position)" />
</xsl:call-template>
<xsl:call-template name="associative-array">
<xsl:with-param name="level" select="$level + 1" />
<xsl:with-param name="array-name" select="'other'" />
<xsl:with-param name="array-members" select="*[not(self::id)][not(self::name)]
[not(self::street)][not(self::postcode)]
[not(self::job)][not(self::position)]" />
</xsl:call-template>
</xsl:template>
<xsl:template name="associative-array">
<xsl:param name="level" as="xs:integer" />
<xsl:param name="array-name" as="xs:string" />
<xsl:param name="array-members"/>
<xsl:value-of select="concat( zzart:indent( $level), $array-name, ': {')" />
<xsl:for-each select="$array-members">
<xsl:value-of select="concat( local-name(), ': ', text(), if (position() != last()) then ', ' else ' }
')" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>