我有一个非结构化的Adlib XML文件,其中包含以下格式的数据:
<record>
...
<dimension.type>height</dimension.type>
<dimension.type>width</dimension.type>
<dimension.type>height</dimension.type>
<dimension.type>width</dimension.type>
<dimension.type>depth</dimension.type>
<dimension.notes>without frame</dimension.notes>
<dimension.notes>without frame</dimension.notes>
<dimension.notes>with frame</dimension.notes>
<dimension.notes>with frame</dimension.notes>
<dimension.notes>with frame</dimension.notes>
<dimension.value>28.0</dimension.value>
<dimension.value>47.9</dimension.value>
<dimension.value>41.4</dimension.value>
<dimension.value>62.9</dimension.value>
<dimension.value>8.0</dimension.value>
...
</record>
我想做的是将其转换为以下格式:
<record>
...
<dimension>
<notes>without frame</notes>
<height>28.0</height>
<width>47.9</width>
</dimension>
<dimension>
<notes>with frame</notes>
<height>41.4</height>
<width>62.9</width>
<depth>8.0</depth>
</dimension>
...
</record>
但是我有点卡住了,因为这些节点引用了同一位置的其他节点中的信息。我确实提出了以下XSLT:
<xsl:template match="dimension.value">
<xsl:variable name="pos" select="position()"/>
<dimension>
<xsl:choose>
<xsl:when test="../dimension.type[$pos] = 'height'">
<height><xsl:value-of select="."/></height>
</xsl:when>
<xsl:when test="../dimension.type[$pos] = 'width'">
<width><xsl:value-of select="."/></width>
</xsl:when>
<xsl:when test="../dimension.type[$pos] = 'depth'">
<depth><xsl:value-of select="."/></depth>
</xsl:when>
</xsl:choose>
<notes>
<xsl:value-of select="../dimension.notes[$pos]"/>
</notes>
</dimension>
</xsl:template>
以下列格式生成数据:
<dimension>
<height>28.0</height>
<notes>without frame</notes>
</dimension>
<dimension>
<width>47.9</width>
<notes>without frame</notes>
</dimension>
<dimension>
<height>41.4</height>
<notes>with frame</notes>
</dimension>
<dimension>
<width>62.9</width>
<notes>with frame</notes>
</dimension>
<dimension>
<depth>8.0</depth>
<notes>with frame</notes>
</dimension>
但是这不会对note部分进行分组,这会使处理结果更容易一些(现在我在代码中解决了这个问题,但是XSLT必须有一种方法来实现它,对吧?)。任何帮助(指向相关信息或相关XSLT片段)将不胜感激......
BTW我翻译了部分XML / XSLT以便于理解,when:test实际检查荷兰语描述并将它们转换为等效的英语标签......
答案 0 :(得分:2)
这是一个XSLT 1.0解决方案:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="record">
<xsl:copy>
<xsl:apply-templates select="dimension.notes[1]" mode="group"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dimension.notes" mode="group">
<dimension>
<notes>
<xsl:value-of select="."/>
</notes>
<xsl:apply-templates select="."/>
</dimension>
<xsl:apply-templates select="following-sibling::dimension.notes[not(. = current())][1]" mode="group"/>
</xsl:template>
<xsl:template match="dimension.notes">
<xsl:variable name="pos">
<xsl:number/>
</xsl:variable>
<xsl:apply-templates select="../dimension.type[position() = $pos]">
<xsl:with-param name="pos" select="$pos"/>
</xsl:apply-templates>
<xsl:apply-templates select="following-sibling::dimension.notes[1][. = current()]"/>
</xsl:template>
<xsl:template match="dimension.type">
<xsl:param name="pos"/>
<xsl:element name="{.}">
<xsl:value-of select="../dimension.value[position() = $pos]"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
以下是使用XSLT 2.0的一些示例:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="record">
<xsl:copy>
<xsl:for-each-group select="dimension.notes" group-adjacent=".">
<dimension>
<notes>
<xsl:value-of select="current-grouping-key()"/>
</notes>
<xsl:apply-templates select="current-group()"/>
</dimension>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="dimension.notes">
<xsl:variable name="pos" as="xs:integer">
<xsl:number/>
</xsl:variable>
<xsl:apply-templates select="../dimension.type[position() eq $pos]">
<xsl:with-param name="pos" select="$pos"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="dimension.type">
<xsl:param name="pos"/>
<xsl:element name="{.}">
<xsl:value-of select="../dimension.value[position() eq $pos]"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我不确定它是否解决了您的问题,因为您的示例中的“...”可能需要更复杂的编码,具体取决于那里可能出现的元素类型以及您想要对它们执行的操作。