合并两个xml ......再次

时间:2014-01-31 23:39:08

标签: xml xslt merge

我对xslt的了解是有限的,但是我已经花了好几个小时并尝试了许多不同的脚本而没有运气。 这是情节: 我们的服务器上有一个xml数据库文件,每次启动软件时都会读取一个软件。我们大约有10个用户使用此文件。新条目存储在本地的类似文件中,我们需要更新服务器文件以包含每周新的本地存储条目。 我已经上传了本地文件的上传功能。上载的文件存储在数据库文件上方的目录中。两个文件的名称相同,但存储在不同的目录中。

这是我最接近的事情,从这个网站复制一个前solutin,只是更改名称。 这里的示例文件只有很少的条目用于测试目的。

“原始”XML:companyroutes.xml

 <?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xml" href="merge2.xsl"?> 
<companyroutes>
  <route name="ENGMEKCH">ENGM OKSAT L996 SVD EKCH</route>

</companyroutes>

上传的XML:/upload/companyroutes.xml

<?xml version="1.0" encoding="utf-8"?>
<companyroutes>
   <route name="ENVAENBR">ENVA GEVLI Z108 ROXET ENBR</route>
   <route name="ENGMEKCH">ENGM OKSAT L996 SVD EKCH</route>
   <route name="ABCDEFGH">ABCD TULLA L666 BAREN EFGH</route>

</companyroutes>

这是xsl合并脚本:merge2.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:param name="fileName" select="'/upload/companyroutes.xml'" />
  <xsl:param name="updates" select="document($fileName)" />

  <xsl:variable name="updateRoute" select="$updates/companyroutes/route" />

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

  <xsl:template match="companyroutes">
    <xsl:copy>
      <xsl:apply-templates select="route[not(@id = $updateRoute/@id)]" />
      <xsl:apply-templates select="$updateRoute" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

我需要包含的另外两个功能是只复制到原始版本的独特Childs,并且能够像我们今天在这个网址上一样在浏览器中查看原始文件:[http://www.xxxxx.org/cr/ companyroutes.xml] [1] 当我尝试在第二个.xsl文件中插入链接进行合并时,我在网址上看不到任何信息。

以下是在网页上转换xml到HTML表格的cr.xsl:

<?xml version="1.0" encoding="ISO-8859-1"?>

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

<xsl:template match="/">
  <html>
  <body>
  <h2>BBL - CompanyRoutes</h2>
  <table border="1" cellspacing="0" cellpadding="2">
    <tr>
      <th>Route Name</th>
      <th>Route</th>
    </tr>
    <xsl:for-each select="//route">
    <tr>
      <td><xsl:value-of select="./@name"/></td>
      <td><xsl:value-of select="./text()"/></td>
    </tr>
    </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

这里有两个问题。

首先,在您的合并XSLT中,您正在执行此操作

<xsl:apply-templates select="route[not(@id = $updateRoute/@id)]" /> 

您正在匹配@id属性,但在XML中它似乎是应该使用的@name属性。因此声明应该如下所示

 <xsl:apply-templates select="route[not(@name = $updateRoute/@name)]" /> 

您还谈到在浏览器中查看它,并查看您链接到的XML,您在XML的顶部有两个xml样式表处理指令(尽管您只在问题的XML示例中显示一个)

<?xml-stylesheet type="text/xsl" href="cr.xsl"?>
<?xml-stylesheet type="text/xml" href="merge2.xsl"?> 

这表明您可能期望应用两个转换。 cr.xsl 应用于 merge2.xsl 转换的结果。我不相信这是可能的。即使有可能,也不会覆盖原始XML。它正在创建一个全新的XML文档显示。

你可以做的是将两个XSLT样式表合并为一个,并使用它,如果你纯粹想在浏览器中看到合并的结果

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:param name="fileName" select="'upload.xml'"/>
  <xsl:param name="updates" select="document($fileName)"/>

  <xsl:variable name="updateRoute" select="$updates/companyroutes/route"/>

  <xsl:template match="companyroutes">
    <html>
      <body>
        <h2>BBL - CompanyRoutes</h2>
        <table border="1" cellspacing="0" cellpadding="2">
          <tr>
            <th>Route Name</th>
            <th>Route</th>
          </tr>
          <xsl:for-each select="route[not(@name = $updateRoute/@name)]|$updateRoute">
            <xsl:sort select="@name"/>
            <tr>
              <td>
                <xsl:value-of select="./@name"/>
              </td>
              <td>
                <xsl:value-of select="./text()"/>
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

当然,如果您确实想要使用合并覆盖原始XML,那么使用此方法是不可能的。在XML中添加 xml-stylesheet 处理指令不会导致原始XML被覆盖。 (请记住,转换是在客户端上,在浏览器中完成的,但您的文件存储在服务器上。)

您将不得不使用服务器语言(如PHP或ASP.Net)或其他方式调查服务器上的转换,具体取决于您当前使用的架构。