首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用XSLT将非结构化(Adlib) XML转换为结构化XML,对相似节点进行分组

使用XSLT将非结构化(Adlib) XML转换为结构化XML,对相似节点进行分组
EN

Stack Overflow用户
提问于 2011-08-30 18:41:42
回答 2查看 416关注 0票数 1

我有一个非结构化的Adlib XML文件,其中包含以下格式的数据:

代码语言:javascript
复制
<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>

我想要做的是将其转换为以下格式:

代码语言:javascript
复制
<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:

代码语言:javascript
复制
<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>

它会生成以下格式的数据:

代码语言:javascript
复制
<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片段的指针)都将非常感谢……

顺便说一句,我翻译了XML/XSLT的一部分以使其更容易理解,when:test实际上检查荷兰语描述,并将它们转换为等效的英语标记……

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-30 20:42:17

下面是一个XSLT 1.0解决方案:

代码语言:javascript
复制
<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>
票数 2
EN

Stack Overflow用户

发布于 2011-08-30 19:36:22

下面是一些使用XSLT 2.0的示例:

代码语言:javascript
复制
<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>

我不确定它能不能解决你的问题,因为"...“您的示例中的元素可能需要更复杂的编码,这取决于那里到底可以出现什么类型的元素以及您想要对它们做什么。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7241961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档