【问题标题】:XSLT Dynamically merge two xml files using filter on elementXSLT 使用元素上的过滤器动态合并两个 xml 文件
【发布时间】:2014-09-08 22:41:21
【问题描述】:

我是xslt的新手,我有两个xml文件如下file1.xml:

<?xml version="1.0" encoding="UTF-8"?>
<people-data id="test-id" timestamp="20014-03-30T09:00:00">
   <person>
      <id>12345</id>
      <first-name>John</first-name>
   </person>

   <person>
      <id>67890</id>
      <first-name>Mike</first-name>
   </person>

   <person>
      <id>11111</id>
      <first-name>Dan</first-name>
   </person>
</people-data>

第二个xml文件如下file2.xml:

<?xml version='1.0' encoding='UTF-8'?>
<people-appointment-data>
    <person-data>        
        <id>12345</id>
        <first-name>John</first-name>       
        <appointments>
          <appointment>
            <code>5124</code>
            <pass>14920329324</pass>
            <states>
                <state>IL</state>
                <state>IN</state>
            </states>
         </appointment>

          <appointment>
            <code>1001</code>
            <pass>14921119324</pass>
            <states>
                <state>NV</state>
                <state>CA</state>
            </states>
         </appointment>
    </appointments>
</person-data>
<person-data>        
    <id>67890</id>
    <first-name>Mike</first-name>       
    <appointments>
        <appointment>
            <code>6666</code>
            <pass>14920</pass>
            <states>
                <state>AK</state>
                <state>MA</state>
            </states>
        </appointment>
    </appointments>
</person-data>
</people-appointment-data>

我试图使用 xslt 实现的是将约会信息复制到第一个 xml 文件中,过滤 id 标签上的匹配项。

如果 id 不匹配,这就是我期望的输出结果,file1.xml 中的信息将被保留:

<?xml version="1.0" encoding="UTF-8"?>
<people-data id="test-id" timestamp="20014-03-30T09:00:00">
   <person>
      <id>12345</id>
      <first-name>John</first-name>
      <appointments>
            <appointment>
                <code>5124</code>
                <pass>14920329324</pass>
                <states>
                    <state>IL</state>
                    <state>IN</state>
                </states>
            </appointment>

          <appointment>
            <code>1001</code>
            <pass>14921119324</pass>
            <states>
                <state>NV</state>
                <state>CA</state>
            </states>
         </appointment>
        </appointments>
   </person>

   <person>
      <id>67890</id>
      <first-name>Mike</first-name>
      <appointments>
            <appointment>
                <code>6666</code>
                <pass>14920</pass>
                <states>
                    <state>AK</state>
                    <state>MA</state>
                </states>
            </appointment>
        </appointments>
   </person>

   <person>
      <id>11111</id>
      <first-name>Dan</first-name>
   </person>
</people-data>

【问题讨论】:

  • 请说明您使用的 XSLT 版本 - 1.0 或 2.0。
  • 你能指导我使用 XSLT 1.0 吗,下面给出的当前解决方案不起作用。 @michael.hor257k
  • 虽然“当前的解决方案”非常糟糕,但它仍然应该“有效”,因为它应该得到每个人的约会。所以我建议你先让事情正常工作。
  • 感谢您的及时回复,我的 xml 文件中有一个错误,带有结束标记。下面给出的解决方案是有效的。你有什么改进的建议?我对 xslt 很陌生,还在学习。 @michael.hor257k

标签: xml xslt


【解决方案1】:

我建议你这样做:

XSLT 1.0

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

<xsl:param name="lookup-document" select="document('file2.xml')"/>
<xsl:key name="pdata" match="person-data" use="id" />

<xsl:template match="/">
    <people-data>
        <xsl:for-each select="people-data/person">
            <person>
                <xsl:variable name="id" select="id" />
                <xsl:copy-of select="*"/>
                <!--  switch context to lookup-document in order to use the key -->
                <xsl:for-each select="$lookup-document">
                    <xsl:copy-of select="key('pdata', $id)/appointments"/>
                </xsl:for-each> 
            </person>
        </xsl:for-each>
    </people-data>
</xsl:template>

</xsl:stylesheet>

【讨论】:

  • 我有一个查询,如果有两个属性值我想复制到合并文件中,例如我已经更新了问题 (id="test-id" timestamp="20014-03- 30T09:00:00") 我应该如何修改这个解决方案。我尝试使用 但它没有被复制为空白。
  • @user2603537 这与您从另一个文档中检索数据的原始问题完全无关; 2. 您可以通过在&lt;people-data&gt; 之后立即添加&lt;xsl:copy-of select="people-data/@*"/&gt; 指令来轻松解决此问题。如果这对您不起作用,我建议您发布一个单独的问题(并关闭此问题)。
【解决方案2】:

document() 函数可让您匹配备用文档中的值。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
    <xsl:apply-templates select="//person"/>
</xsl:template>
<xsl:template match="person">
    <xsl:copy>
        <xsl:apply-templates select="*" mode="copy"/>
        <xsl:variable name="id" select="id/text()"/>
        <xsl:apply-templates select="document('file2.xml')//person-data[id/text()=$id]/appointments" mode="copy"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*" mode="copy">
    <xsl:copy>
        <xsl:apply-templates select="*|text()" mode="copy"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

【讨论】:

  • 你怎么测试这个,我试图在网上寻找 xml/xslt 测试仪,但只是偶然发现了一个允许你使用一个 xml 文件作为输入的网站?
  • 我有一个 XML 编辑器/XSLT 编辑器,所以我在我的文件系统上进行了测试。为了在网络上进行测试,您需要可以从网络服务器访问两个输入文件。
  • 您能指导我您使用的是什么 XML 编辑器/XSLT 编辑器吗?
  • 我使用过 Oxygen XML Editor 和 Altova XML Spy。 Eclipse 还可能提供一个用于 XSLT 编辑的插件。
  • 我尝试运行上面的 XSLT,我正在使用 Pentaho 运行 xslt。我似乎没有按我的意愿工作。 12345John 67890Mike11111Dan 约会没有不要被复制。
猜你喜欢
  • 2013-10-02
  • 1970-01-01
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-17
  • 2019-08-25
相关资源
最近更新 更多