使用 XSLT 1.0 将平面 XML 表数据(其中元素由行和列名称串联而成)转换为嵌套 XML

2024-05-19

我有 XML 输出,表示输出的数据表,如下所示:

<results>
  <Row1.Name>Henry</Row1.Name>
  <Row1.Id>P162</Row1.Id>
  <Row1.Age>23</Row1.Age>
  <Row2.Name>John</Row2.Name>
  <Row2.Id>P137</Row2.Id>
  <Row2.Age>27</Row2.Age>
  <Row3.Name>Mary</Row3.Name>
  <Row3.Id>L493</Row3.Id>
  <Row3.Age>32</Row3.Age>
</results>

我想把它转换成这样:

<results>
  <Row>
    <Name>Henry</Name>
    <Id>P162<Id>
    <Age>23</Age>
  </Row>
  <Row>
    <Name>John</Name>
    <Id>P137<Id>
    <Age>27</Age>
  </Row>
  <Row>
    <Name>Mary</Name>
    <Id>L493<Id>
    <Age>32</Age>
  </Row>
</results>

我正在使用的应用程序迫使我使用 XSLT 1.0,我确信这真的很简单,但我今天有一个心理障碍,所以我想我应该问我的虚拟同事。

有人有什么想法吗?

注意:修改了所需的输出以不显示迭代行号,这正是我想要的。

还没有任何接近工作的东西。仍然在玩弄不同的东西。

我想我可以写这样的东西:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
    <xsl:variable name="Row" select="distinct-values(*[contains(name(),'Row')])" />
           <xsl:for-each select="$Row">
               <xsl:variable name="rowName" select="name()" />
               <Row>
                   <xsl:for-each select="*[contains(name(),$Row)]">
                       <xsl:copy select="." />
                   </xsl:for-each>
               </Row>
           </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

产生这个:

<results>
    <Row>
        <Row1.Name>Henry</Row1.Name>
        <Row1.Id>P162</Row1.Id>
        <Row1.Age>23</Row1.Age>
    </Row>
    <Row>
        <Row2.Name>John</Row2.Name>
        <Row2.Id>P137</Row2.Id>
        <Row2.Age>27</Row2.Age>
    </Row>
    <Row>
        <Row3.Name>Mary</Row3.Name>
        <Row3.Id>L493</Row3.Id>
        <Row3.Age>32</Row3.Age>
   </Row>
</results>

然后返回并删除所有 Row# 前缀:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/*[contains(name(),'.')]">
        <xsl:variable name="Name" select="substring-after(name(),'.')" />
        <xsl:element name="{$Name}">
            <xsl:value-of select="." />
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

但这两种转换都不起作用,我认为我不能使用distinct-values使用 XSLT 1.0


这是一个分组问题,XSLT 1.0 中解决此类问题的标准方法称为慕尼黑分组。您定义一个键,以您想要的方式对元素进行分组,然后使用一个技巧generate-id每组仅处理一个元素。在这种情况下,您希望按元素名称的点之前的部分对元素进行分组:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:key name="elementByRow" match="/*/*"
           use="substring-before(name(), '.')" />

  <xsl:template match="/results">
    <results>
      <!-- pick out the first RowN.* element for each N -->
      <xsl:apply-templates select="*[generate-id() =
         generate-id(key('elementByRow', substring-before(name(), '.'))[1])]" />
    </results>
  </xsl:template>

  <xsl:template match="*">
    <Row>
      <!-- process _all_ the elements that belong to this row -->
      <xsl:for-each select="key('elementByRow', substring-before(name(), '.'))">
        <xsl:element name="{substring-after(name(), '.')}">
          <xsl:value-of select="." />
        </xsl:element>
      </xsl:for-each>
    </Row>
  </xsl:template>
</xsl:stylesheet>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 XSLT 1.0 将平面 XML 表数据(其中元素由行和列名称串联而成)转换为嵌套 XML 的相关文章

随机推荐