【问题标题】:How can I combine child nodes across two or more XML files using XSL?如何使用 XSL 跨两个或多个 XML 文件组合子节点?
【发布时间】:2011-11-03 05:15:51
【问题描述】:

我正在尝试使用 XSL 组合 XML 文件。我在 stackoverflow、google 和其他地方寻找线索。我发现了类似的问题或主题,但没有一个与我想要做的完全匹配。

我已尝试利用从这些来源中收集到的信息,但似乎无法完全得到我正在寻找的结果。所以...到 S/O 进行快速咨询!

这是我目前的做法:

输入文件1.xml

<?xml version="1.0" encoding="UTF-8"?>
<protocol>
  <message_exchanges>
    <message_exchange id="1"/>
    <message_exchange id="2"/>
  </message_exchanges>
  <message_types>
    <message_type id="1"/>
    <message_type id="2"/>
    <message_type id="3"/>
  </message_types>
</protocol>

输入文件2.xml

<?xml version="1.0" encoding="UTF-8"?>
<protocol>
  <message_exchanges>
    <message_exchange id="3"/>
    <message_exchange id="4"/>
  </message_exchanges>
  <message_types>
    <message_type id="4"/>
    <message_type id="5"/>
    <message_type id="6"/>
  </message_types>
</protocol>

输入 index.xml

<?xml version="1.0" encoding="UTF-8"?>
<index>
  <component>file1.xml</component>
  <component>file2.xml</component>
</index>

combine.xsl

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

<xsl:output method="xml" version="1.0" indent="yes"/>

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

<xsl:template match="component">
  <xsl:apply-templates select="document(.)"/>
</xsl:template>

.....help me fix / finish this file

</xsl:stylesheet>

desired_result.xml

<?xml version="1.0" encoding="UTF-8"?>
<protocol>
  <message_exchanges>
    <message_exchange id="1"/>
    <message_exchange id="2"/>
    <message_exchange id="3"/>
    <message_exchange id="4"/>
  </message_exchanges>
  <message_types>
    <message_type id="1"/>
    <message_type id="2"/>
    <message_type id="3"/>
    <message_type id="4"/>
    <message_type id="5"/>
    <message_type id="6"/>
  </message_types>
</protocol>

1,000 奖励积分,如果您能帮我即时添加属性:

<message_type id="1" src="file1.xml"/>
<message_type id="4" src="file2.xml"/>

我正在使用 PHP 的 XSLTProcessor 加载 XSL 文件并将其应用到 XML 索引文件,因此如果添加 src 属性有用/更容易实现,我可以将源文件名作为参数加载到处理器中。

谢谢!让我知道是否可以进一步澄清。

The most useful link I've found so far and the basis of my current approach

【问题讨论】:

  • 糟糕,不,不是故意的。现已修复。
  • 好问题,+1。请参阅我的答案以获得相当简短、通用且直接的解决方案。

标签: php xml xslt


【解决方案1】:

这是模板参数变得有用的情况。这是我实际上能够产生的最短和最简单的转换。 它处理两个或更多文件。

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

    <xsl:template match="index">
        <protocol>
            <message_exchanges>
                <xsl:apply-templates select="component">
                    <xsl:with-param name="message" select="'message_exchanges'"/>
                </xsl:apply-templates>
            </message_exchanges>
            <message_types>
                <xsl:apply-templates select="component">
                    <xsl:with-param name="message" select="'message_types'"/>
                </xsl:apply-templates>
            </message_types>
        </protocol>
    </xsl:template>

    <xsl:template match="component">
        <xsl:param name="message"/>
        <xsl:apply-templates select="document(.)/*/*[name()=$message]/*">
            <xsl:with-param name="comp" select="."/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="message_type|message_exchange">
        <xsl:param name="comp" select="''"/>
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:attribute name="src">
                <xsl:value-of select="$comp"/>
            </xsl:attribute>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

带输出:

<protocol>
   <message_exchanges>
      <message_exchange id="1" src="file1.xml"/>
      <message_exchange id="2" src="file1.xml"/>
      <message_exchange id="3" src="file2.xml"/>
      <message_exchange id="4" src="file2.xml"/>
   </message_exchanges>
   <message_types>
      <message_type id="1" src="file1.xml"/>
      <message_type id="2" src="file1.xml"/>
      <message_type id="3" src="file1.xml"/>
      <message_type id="4" src="file2.xml"/>
      <message_type id="5" src="file2.xml"/>
      <message_type id="6" src="file2.xml"/>
   </message_types>
</protocol>

【讨论】:

  • 感谢您的回答,并感谢您将其设计为处理可变数量的输入文件(这确实是我想要的)。
【解决方案2】:

这种转变

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vFilename1" select="/*/component[1]"/>
 <xsl:variable name="vFilename2" select="/*/component[2]"/>

 <xsl:template match="index">
  <protocol>
    <xsl:apply-templates select="document($vFilename1)"/>
  </protocol>
 </xsl:template>

 <xsl:template match="message_exchanges|message_types">
  <xsl:copy>
   <xsl:apply-templates/>

   <xsl:apply-templates select=
       "document($vFilename2)/*/*[name()=name(current())]/*">
     <xsl:with-param name="pFilename" select="$vFilename2"/>
   </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="message_exchanges/* | message_types/*">
  <xsl:param name="pFilename" select="$vFilename1"/>

  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:attribute name="src">
    <xsl:value-of select="$pFilename"/>
   </xsl:attribute>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<index>
  <component>file1.xml</component>
  <component>file2.xml</component>
</index>

产生想要的正确结果

<protocol>
   <message_exchanges>
      <message_exchange id="1" src="file1.xml"/>
      <message_exchange id="2" src="file1.xml"/>
      <message_exchange id="3" src="file2.xml"/>
      <message_exchange id="4" src="file2.xml"/>
   </message_exchanges>
   <message_types>
      <message_type id="1" src="file1.xml"/>
      <message_type id="2" src="file1.xml"/>
      <message_type id="3" src="file1.xml"/>
      <message_type id="4" src="file2.xml"/>
      <message_type id="5" src="file2.xml"/>
      <message_type id="6" src="file2.xml"/>
   </message_types>
</protocol>

【讨论】:

  • 问题实际上是在问“如何使用 XSL 跨两个或多个 XML 文件组合子节点?”
  • @empo,您的评论与我的回答有何关系?
  • 您似乎已经展示了如何跨两个特定的 XML 文件组合子节点。如果您说要合并 100 个文件,则呈现的转换不是很有用。请参阅我的答案以获得更通用的解决方案。
  • @empo,是的,这就是 OP 想要的。有许多可能的概括,不值得花时间去假设。
  • 标题要求“两个或更多”文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
  • 2020-06-16
  • 2015-09-17
  • 1970-01-01
  • 2019-01-29
相关资源
最近更新 更多