【问题标题】:Unusual XSLT transformation - structuralization of XML不寻常的 XSLT 转换 - XML 的结构化
【发布时间】:2013-02-05 23:32:15
【问题描述】:

我遇到了一些不寻常的问题。我的任务是“结构化 XML”。这是一个输入 XML(示例):

<documents>
  <document>Review</document>
  <document_id>REV#1</document_id>
  <item>List of terms</item>
  <item_id>10</item_id>
  <item_description>Terms used in documents</item_description>
  <item_attribute>Term</item_attribute>
  <item_attribute_name>SA</item_attribute_name>
  <item_attribute_value>Some Attribute</item_attribute_value>
  <item_attribute_name>SOA</item_attribute_name>
  <item_attribute_value>Some Other Attribute</item_attribute_value>

  <document>Interface</document>
  <document_id>AC-163</document_id>
  <item>List of terms</item>
  <item_id>15</item_id>
  <item_description>Another item</item_description>
  <item_attribute>Term</item_attribute>
  <item_attribute_name>Name#1</item_attribute_name>
  <item_attribute_value>Att#1</item_attribute_value>
  <item_attribute_name>Name#2</item_attribute_name>
  <item_attribute_value>Att#2</item_attribute_value>
</documents>

我应该做的是将其转换为以下实体结构:

文档 1..* 文档 1..1 项目 1..* 项目 1..1 属性 1..* 属性

这意味着:元素'documents'可能包含许多'document','document'只包含一个名为'items'的元素,元素'items'可能包含许多元素'item',等等。

上面例子的预期输出是:

<documents>
    <document>
        <document_id>REV#1</document_id>
        <items>
            <item>
                <id>10</id>
                <description>Terms used in documents</description>
                <attributes>
                    <attribute>
                        <name>SA</name>
                        <value>Some Attribute</value>
                    </attribute>
                    <attribute>
                        <name>SOA</name>
                        <value>Some Other Attribute</value>
                    </attribute>
                </attributes>
            </item>
        </items>
    </document>
    <document>
        <document_id>AC-163</document_id>
        <items>
            <item>
                <id>15</id>
                <description>Another item</description>
                <attributes>
                    <attribute>
                        <name>Name#1</name>
                        <value>Att#1</value>
                    </attribute>
                    <attribute>
                        <name>Name#2</name>
                        <value>Att#2</value>
                    </attribute>
                </attributes>
            </item>
        </items>
    </document>
</documents>

我在这项任务中遇到了一些麻烦.... 可以请您帮忙吗?这是一些不寻常的“结构化”xml - 你有什么想法吗?

最好的问候!

【问题讨论】:

    标签: xml xslt transformation


    【解决方案1】:

    如果您使用的是 XSLT 2.0,这应该很容易通过 XSLT grouping 实现,但如果您被 XSLT 1.0 卡住,这里有一个兼容 XSLT 1.0 的解决方案。

    样式表

    <?xml version="1.0" encoding="UTF-8"?>
    
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" indent="yes"/>
    
      <!-- Identity transform -->
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="document">
        <!-- Store the unique ID of the current element into a variable. -->
        <xsl:variable name="id" select="generate-id()"/>
    
        <xsl:copy>
          <xsl:apply-templates select="following-sibling::document_id[1]"/>
          <items>
            <!--
            Apply all <item_attribute_name> elements whose first preceding
            <document> sibling is the element that's currently being processed. This
            is to keep from processing *all* of the rest of the
            <item_attribute_name> elements in the document.
            -->
            <xsl:apply-templates select="following-sibling::item
              [preceding-sibling::document[1][generate-id() = $id]]"/>
          </items>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="item">
        <xsl:variable name="id" select="generate-id()"/>
    
        <xsl:copy>
          <xsl:apply-templates select="following-sibling::item_id[1]"/>
          <xsl:apply-templates select="following-sibling::item_description[1]"/>
          <attributes>
            <xsl:apply-templates select="following-sibling::item_attribute_name
              [preceding-sibling::item[1][generate-id() = $id]]"/>
          </attributes>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="documents">
        <xsl:copy>
          <xsl:apply-templates select="document"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="item_description">
        <description>
          <xsl:apply-templates/>
        </description>
      </xsl:template>
    
      <xsl:template match="item_id">
        <id>
          <xsl:apply-templates/>
        </id>
      </xsl:template>
    
      <xsl:template match="item_attribute_name">
        <attribute>
          <name>
            <xsl:apply-templates/>
          </name>
    
          <xsl:apply-templates select="following-sibling::item_attribute_value[1]"/>
        </attribute>
      </xsl:template>
    
      <xsl:template match="item_attribute_value">
        <value>
          <xsl:apply-templates/>
        </value>
      </xsl:template>
    
      <xsl:template match="item_attribute"/>
    
    </xsl:stylesheet>
    

    输入

    <documents>
      <document>Review</document>
      <document_id>REV#1</document_id>
      <item>List of terms</item>
      <item_id>10</item_id>
      <item_description>Terms used in documents</item_description>
      <item_attribute>Term</item_attribute>
      <item_attribute_name>SA</item_attribute_name>
      <item_attribute_value>Some Attribute</item_attribute_value>
      <item_attribute_name>SOA</item_attribute_name>
      <item_attribute_value>Some Other Attribute</item_attribute_value>
    
      <document>Interface</document>
      <document_id>AC-163</document_id>
      <item>List of terms</item>
      <item_id>15</item_id>
      <item_description>Another item</item_description>
      <item_attribute>Term</item_attribute>
      <item_attribute_name>Name#1</item_attribute_name>
      <item_attribute_value>Att#1</item_attribute_value>
      <item_attribute_name>Name#2</item_attribute_name>
      <item_attribute_value>Att#2</item_attribute_value>
    </documents>
    

    输出

    <?xml version="1.0"?>
    <documents>
      <document>
        <document_id>REV#1</document_id>
        <items>
          <item>
            <id>10</id>
            <description>Terms used in documents</description>
            <attributes>
              <attribute>
                <name>SA</name>
                <value>Some Attribute</value>
              </attribute>
              <attribute>
                <name>SOA</name>
                <value>Some Other Attribute</value>
              </attribute>
            </attributes>
          </item>
        </items>
      </document>
      <document>
        <document_id>AC-163</document_id>
        <items>
          <item>
            <id>15</id>
            <description>Another item</description>
            <attributes>
              <attribute>
                <name>Name#1</name>
                <value>Att#1</value>
              </attribute>
              <attribute>
                <name>Name#2</name>
                <value>Att#2</value>
              </attribute>
            </attributes>
          </item>
        </items>
      </document>
    </documents>
    

    【讨论】:

    • 我称之为“兄弟递归”的技术的一个很好的例子。但是 XSLT 2.0 位置分组更容易......
    • @michael-kay:谢谢!完全同意 XSLT 2.0 分组更容易——我只是选择了 XSLT 1.0,因为问题中没有指定 XSLT 版本。
    • 它有效,但你为什么认为“项目”只包含一个“项目”等? :(
    • 我修改了我的答案以在下一个 &lt;document&gt; 元素之前考虑多个关注 &lt;item&gt; 兄弟姐妹。
    猜你喜欢
    • 1970-01-01
    • 2011-01-17
    • 2012-05-31
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    相关资源
    最近更新 更多