1

又是一个有问题的任务。我有一个不太好的 xml。例如以下:

<?xml version="1.0" encoding="UTF-8"?>
<Values>
<record name='svc_sig'>
<record name="sig_in">
    <array depth="1" name="rec_fields" type="record">
        <record>
            <!-- Some irrelevant metadata information with value node name... -->
            <value name="field_name">docTest</value>
            <value name="field_type">record</value>
            <value name="field_dim">0</value>
            <array depth="1" name="rec_fields" type="record">
                <record javaclass="com.wm.util.Values">
                    <!-- Some irrelevant metadata information with value node name... -->
                    <value name="field_name">doc.name</value>
                    <value name="field_type">string</value>
                    <value name="field_dim">0</value>
                </record>
            </array>
        </record>
        <record>
            <value name="field_name">docListTest</value>
            <value name="field_type">record</value>
            <value name="field_dim">1</value>
            <array depth="1" name="rec_fields" type="record">
                <record>
                    <value name="field_name">d0</value>
                    <value name="field_type">record</value>
                    <value name="field_dim">0</value>
                    <array depth="1" name="rec_fields" type="record">
                        <record>
                            <value name="field_name">d0.name</value>
                            <value name="field_type">string</value>
                            <value name="field_dim">0</value>
                        </record>
                    </array>
                </record>
            </array>
        </record>
        <record>
            <value name="field_name">packages_should_work</value>
            <value name="field_type">recref</value>
            <value name="field_dim">0</value>
            <value name="rec_ref">data:packages</value>
        </record>
        <record>
            <value name="field_name">packages_list_should_work</value>
            <value name="field_type">recref</value>
            <value name="field_dim">1</value>
            <value name="rec_ref">data:packages</value>
        </record>
    </array>
</record>
</record>
</Values>

为简单起见,我需要将此 xml 映射到已经给出的 java 类,我无法更改它。考虑到这一点,我必须将此 xml 转换为另一个具有有意义名称的 xml。例如:

<sig_in>
   <record>
      <field_name>docTest</field_name>
      <field_type>record</field_type>
      <field_dim>0</field_dim>
   </record>
   <record>
      <field_name>docListTest</field_name>
      <field_type>record</field_type>
      <field_dim>1</field_dim>
   </record>
   <record>
      <field_name>packages_should_work</field_name>
      <field_type>recref</field_type>
      <field_dim>0</field_dim>
   </record>
   <record>
      <field_name>packages_list_should_work</field_name>
      <field_type>recref</field_type>
      <field_dim>1</field_dim>
   </record>
</sig_in>

到目前为止,我创建了这样的东西:

<?xml version="1.0" encoding="UTF-8"?>
<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="/" name="service_signature">
        <sig_in>
            <xsl:for-each select="Values/record[@name='svc_sig']/record[@name='sig_in']/array[@name]/record">
                <record>
                    <field_name><xsl:value-of select="value[@name='field_name']/text()"/></field_name>
                    <field_type><xsl:value-of select="value[@name='field_type']/text()"/></field_type>
                    <field_dim><xsl:value-of select="value[@name='field_dim']/text()"/></field_dim>
                </record>
            </xsl:for-each>
        </sig_in>
    </xsl:template>

</xsl:stylesheet>

虽然它适用于主要元素,但不适用于嵌套记录。如果类型是记录,我可以创建一个 xsl:for-each 并遍历每个项目,但这并不能解决太多问题;因为它可以很深。我知道我应该使用递归我只是无法想象在这种特殊情况下我该怎么做。

@Edit - 对嵌套类型的一些更正:

<record>
  <field_name>docListTree</field_name>
  <field_type>record</field_type>
  <field_dim>1</field_dim>
  <record>
    <field_name>d0</field_name>
    <field_type>record</field_type>
    <field_dim>0</field_dim>
    <record>
      <field_name>d0.name</field_name>
      <field_type>string</field_type>
      <field_dim>0</field_dim>
    </record>
  </record>
</record>

因此,您可以看到原始类型的嵌套位置,我在生成的 xml 中也需要相同的类型。或者在公寓里,我需要在父节点和子节点中有一些唯一标识符,这样我就知道哪个包含哪个。无论如何,我不应该松动结构。

@Edit:-真的很抱歉,我想节省空间,但未能展示墙后的复杂性。所以每条记录都包含值名称节点。它们中的大多数只包含我不需要的无用元数据信息。还有两条记录,@name {sig_in, sig_out},我只需要 sig_in,其中包含 field_name、field_type、field_dim 信息,以及以相同方式嵌套的记录。我将查看所有推荐的选项,并尝试修改它们以满足需求。

感谢您的每一个帮助!- 乔

4

3 回答 3

0

此 XSLT 能够生成您发布的结果:

<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="/" name="service_signature">
    <sig_in>
      <xsl:for-each select="/record[@name='sig_in']/array[@name]/record">
        <record>
          <field_name><xsl:value-of select="value[@name='field_name']/text()"/></field_name>
          <field_type><xsl:value-of select="value[@name='field_type']/text()"/></field_type>
          <field_dim><xsl:value-of select="value[@name='field_dim']/text()"/></field_dim>
        </record>
      </xsl:for-each>
    </sig_in>
  </xsl:template>

</xsl:stylesheet>

但是,如果您想遍历每条记录,请使用:

<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="/" name="service_signature">
    <sig_in>
      <xsl:for-each select="//array[@name]/record">
        <record>
          <field_name><xsl:value-of select="value[@name='field_name']/text()"/></field_name>
          <field_type><xsl:value-of select="value[@name='field_type']/text()"/></field_type>
          <field_dim><xsl:value-of select="value[@name='field_dim']/text()"/></field_dim>
        </record>
      </xsl:for-each>
    </sig_in>
  </xsl:template>

</xsl:stylesheet>
于 2013-05-07T07:30:25.070 回答
0

这是一个可以帮助你的xslt。

<?xml version="1.0" encoding="UTF-8"?>
<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="*">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="record|value">
        <xsl:choose>
            <xsl:when test="@name">
                <xsl:element name="{@name}">
                    <xsl:apply-templates/>
                </xsl:element>              
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates/>
                </xsl:copy>             
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

使用您的 XML:

<record name="sig_in">
    <array depth="1" name="rec_fields" type="record">
        <record>
            <value name="field_name">docTest</value>
            <value name="field_type">record</value>
            <value name="field_dim">0</value>
            <array depth="1" name="rec_fields" type="record">
                <record javaclass="com.wm.util.Values">
                    <value name="field_name">doc.name</value>
                    <value name="field_type">string</value>
                    <value name="field_dim">0</value>
                </record>
            </array>
        </record>
        <record>
            <value name="field_name">docListTest</value>
            <value name="field_type">record</value>
            <value name="field_dim">1</value>
            <array depth="1" name="rec_fields" type="record">
                <record>
                    <value name="field_name">d0</value>
                    <value name="field_type">record</value>
                    <value name="field_dim">0</value>
                    <array depth="1" name="rec_fields" type="record">
                        <record>
                            <value name="field_name">d0.name</value>
                            <value name="field_type">string</value>
                            <value name="field_dim">0</value>
                        </record>
                    </array>
                </record>
            </array>
        </record>
        <record>
            <value name="field_name">packages_should_work</value>
            <value name="field_type">recref</value>
            <value name="field_dim">0</value>
            <value name="rec_ref">data:packages</value>
        </record>
        <record>
            <value name="field_name">packages_list_should_work</value>
            <value name="field_type">recref</value>
            <value name="field_dim">1</value>
            <value name="rec_ref">data:packages</value>
        </record>
    </array>
</record>

结果是:

<?xml version="1.0" encoding="utf-8"?>
<sig_in>
   <record>
      <field_name>docTest</field_name>
      <field_type>record</field_type>
      <field_dim>0</field_dim>
      <record>
         <field_name>doc.name</field_name>
         <field_type>string</field_type>
         <field_dim>0</field_dim>
      </record>
   </record>
   <record>
      <field_name>docListTest</field_name>
      <field_type>record</field_type>
      <field_dim>1</field_dim>
      <record>
         <field_name>d0</field_name>
         <field_type>record</field_type>
         <field_dim>0</field_dim>
         <record>
            <field_name>d0.name</field_name>
            <field_type>string</field_type>
            <field_dim>0</field_dim>
         </record>
      </record>
   </record>
   <record>
      <field_name>packages_should_work</field_name>
      <field_type>recref</field_type>
      <field_dim>0</field_dim>
      <rec_ref>data:packages</rec_ref>
   </record>
   <record>
      <field_name>packages_list_should_work</field_name>
      <field_type>recref</field_type>
      <field_dim>1</field_dim>
      <rec_ref>data:packages</rec_ref>
   </record>
</sig_in>
于 2013-05-07T07:42:12.717 回答
0

尝试这样的事情:

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

    <xsl:template match="value[@name]">
        <xsl:element name="{@name}">
            <xsl:value-of select="text()"/>
        </xsl:element>

    </xsl:template>

    <xsl:template match="record">
            <xsl:copy>
                <xsl:apply-templates  />
            </xsl:copy>
    </xsl:template>
     <xsl:template match="/*">
        <xsl:apply-templates  />
    </xsl:template>

    <xsl:template match="node()">
        <xsl:apply-templates select="node()" />
    </xsl:template>
</xsl:stylesheet>

这将生成以下输出:

<?xml version="1.0"?>
<record>
  <field_name>docTest</field_name>
  <field_type>record</field_type>
  <field_dim>0</field_dim>
  <record>
    <field_name>doc.name</field_name>
    <field_type>string</field_type>
    <field_dim>0</field_dim>
  </record>
</record><record>
  <field_name>docListTest</field_name>
  <field_type>record</field_type>
  <field_dim>1</field_dim>
  <record>
    <field_name>d0</field_name>
    <field_type>record</field_type>
    <field_dim>0</field_dim>
    <record>
      <field_name>d0.name</field_name>
      <field_type>string</field_type>
      <field_dim>0</field_dim>
    </record>
  </record>
</record><record>
  <field_name>packages_should_work</field_name>
  <field_type>recref</field_type>
  <field_dim>0</field_dim>
  <rec_ref>data:packages</rec_ref>
</record><record>
  <field_name>packages_list_should_work</field_name>
  <field_type>recref</field_type>
  <field_dim>1</field_dim>
  <rec_ref>data:packages</rec_ref>
</record>

更新有问题的更多信息:

您可以轻松地将某些条件放入记录或值模板中。这就是我所理解的:仅考虑具有@name值为“sig_in”的记录的记录。
试试这个:

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

    <xsl:template match="value[@name = 'field_name' or
                            @name = 'field_type' or
                            @name = 'field_dim']">
        <xsl:element name="{@name}">
            <xsl:value-of select="text()"/>
        </xsl:element>

    </xsl:template>

    <xsl:template match="record[descendant-or-self::record[@name='sig_in'] or 
                  ancestor::record[@name='sig_in']]">
            <xsl:copy>
                <xsl:apply-templates  />
            </xsl:copy>
    </xsl:template>


    <xsl:template match="/*">
        <xsl:apply-templates  />
    </xsl:template>

    <xsl:template match="node()">
        <xsl:apply-templates select="node()" />
    </xsl:template>
</xsl:stylesheet>
于 2013-05-07T08:06:42.433 回答