转换并组合多个xml文档

时间:2015-07-02 11:11:34

标签: xml xslt

我有一个requirement来在Linux下的Apache下托管一个NuGet存储库。设计受到相当大的限制,并要求将包源存储为静态文件。所需输出格式的示例如下:http://chocolatey.org/api/v2/Packages

我试图从* .nupkg档案中找到的* .nuspec文件生成此文档,如下所示:

#!/bin/bash

#for pkg in nxlog git.install; do
#  curl -L http://chocolatey.org/api/v2/package/$pkg -o $pkg.nupkg
#done

unzip "*.nupkg" "*.nuspec"
xsltproc transform.xsl *.nuspec > Packages
rm -f *.nuspec

到目前为止,不正确的转换xslt看起来像这样:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes" />
  <feed xml:base="http://gallery-host/api/v2/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
    <title type="text">Packages</title>
    <id>http://gallery-host/api/v2/Packages</id>
    <updated></updated>
    <link rel="self" title="Packages" href="Packages" />
    <xsl:apply-templates />
  </feed>
  <xsl:template match="metadata">
    <entry>
      <id><xsl:value-of select="id"/></id>
      <title type="text"><xsl:value-of select="title"/></title>
      <summary type="text"><xsl:value-of select="summary"/></summary>
      <updated></updated>
      <author>
        <name><xsl:value-of select="authors"/></name>
      </author>
      <link rel="edit-media" title="V2FeedPackage">
        <xsl:attribute name="href">Packages(Id='<xsl:value-of select="id"/>',Version='<xsl:value-of select="version"/>')/$value</xsl:attribute>
      </link>
      <link rel="edit" title="V2FeedPackage">
        <xsl:attribute name="href">Packages(Id='<xsl:value-of select="id"/>',Version='<xsl:value-of select="version"/>')</xsl:attribute>
      </link>
      <category term="NuGetGallery.V2FeedPackage" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
      <content type="application/zip">
        <xsl:attribute name="src">http://chocolatey.org/api/v2/package/<xsl:value-of select="id"/>/<xsl:value-of select="version"/></xsl:attribute>
      </content>
      <m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
        <d:Version><xsl:value-of select="version"/></d:Version>
        <d:Copyright><xsl:value-of select="copyright"/></d:Copyright>
        <!--
        <d:Created m:type="Edm.DateTime"></d:Created>
        <d:Dependencies></d:Dependencies>
        -->
        <d:Description><xsl:value-of select="description"/></d:Description>
        <!--
        <d:DownloadCount m:type="Edm.Int32"></d:DownloadCount>
        -->
        <d:GalleryDetailsUrl>http://gallery-host/packages/<xsl:value-of select="id"/>/<xsl:value-of select="version"/></d:GalleryDetailsUrl>
        <d:IconUrl><xsl:value-of select="iconUrl"/></d:IconUrl>
        <!--
        <d:IsLatestVersion m:type="Edm.Boolean"></d:IsLatestVersion>
        <d:IsAbsoluteLatestVersion m:type="Edm.Boolean"></d:IsAbsoluteLatestVersion>
        <d:IsPrerelease m:type="Edm.Boolean"></d:IsPrerelease>
        <d:Language m:null="true"></d:Language>
        <d:Published m:type="Edm.DateTime"></d:Published>
        -->
        <d:LicenseUrl><xsl:value-of select="licenseUrl"/></d:LicenseUrl>
        <!--
        <d:PackageHash></d:PackageHash>
        <d:PackageHashAlgorithm></d:PackageHashAlgorithm>
        <d:PackageSize m:type="Edm.Int64"></d:PackageSize>
        -->
        <d:ProjectUrl><xsl:value-of select="projectUrl"/></d:ProjectUrl>
        <!--
        <d:ProjectSourceUrl m:null="true"></d:ProjectSourceUrl>
        <d:PackageSourceUrl m:null="true"></d:PackageSourceUrl>
        <d:DocsUrl m:null="true"></d:DocsUrl>
        <d:MailingListUrl m:null="true"></d:MailingListUrl>
        <d:BugTrackerUrl m:null="true"></d:BugTrackerUrl>
        -->
        <d:ReportAbuseUrl>http://gallery-host/package/ReportAbuse/<xsl:value-of select="id"/>/<xsl:value-of select="version"/></d:ReportAbuseUrl>
        <d:ReleaseNotes><xsl:value-of select="releaseNotes"/></d:ReleaseNotes>
        <!--
        <d:PackageStatus></d:PackageStatus>
        <d:PackageSubmittedStatus m:null="true"></d:PackageSubmittedStatus>
        <d:RequireLicenseAcceptance m:type="Edm.Boolean"></d:RequireLicenseAcceptance>
        -->
        <d:Tags xml:space="preserve"><xsl:value-of select="tags"/></d:Tags>
        <d:Title><xsl:value-of select="title"/></d:Title>
        <!--
        <d:VersionDownloadCount m:type="Edm.Int32"></d:VersionDownloadCount>
        -->
      </m:properties>
    </entry>
  </xsl:template>
</xsl:stylesheet>

这导致输出文件不包含xml标记(正确包含内容)。

如何更正transform.xsl以生成具有多个子<feed>元素的单个根<entry>元素(以便我的输出格式为http://chocolatey.org/api/v2/Packages)?

更新

感谢来自@Martin Honnen的pointer和来自@FrédéricHamidi的another(为什么总是命名空间让你陷入困境,使用xml?),我进一步了解变换:

<?xml version="1.0" ?>
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
  <xsl:template match="/">
    <feed>
      <xsl:for-each select="p:package/p:metadata" xmlns:p="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
        <xsl:element name="entry">
          <xsl:element name="id"><xsl:value-of select="p:id"/></xsl:element>
          <xsl:element name="title">
            <xsl:attribute name="type">text</xsl:attribute>
            <xsl:value-of select="p:title"/>
          </xsl:element>
          <xsl:element name="summary">
            <xsl:attribute name="type">text</xsl:attribute>
            <xsl:value-of select="p:summary"/></xsl:element>
          <xsl:element name="author">
            <xsl:element name="name"><xsl:value-of select="p:authors"/></xsl:element>
          </xsl:element>
          <xsl:element name="link">
            <xsl:attribute name="rel">edit-media</xsl:attribute>
            <xsl:attribute name="title">V2FeedPackage</xsl:attribute>
            <xsl:attribute name="href">Packages(Id='<xsl:value-of select="p:id"/>',Version='<xsl:value-of select="p:version"/>')/$value</xsl:attribute>
          </xsl:element>
          <xsl:element name="link">
            <xsl:attribute name="rel">edit</xsl:attribute>
            <xsl:attribute name="title">V2FeedPackage</xsl:attribute>
            <xsl:attribute name="href">Packages(Id='<xsl:value-of select="p:id"/>',Version='<xsl:value-of select="p:version"/>')</xsl:attribute>
          </xsl:element>
          <xsl:element name="category">
            <xsl:attribute name="term">NuGetGallery.V2FeedPackage</xsl:attribute>
            <xsl:attribute name="scheme">http://schemas.microsoft.com/ado/2007/08/dataservices/scheme</xsl:attribute>
          </xsl:element>
          <xsl:element name="content">
            <xsl:attribute name="type">application/zip</xsl:attribute>
            <xsl:attribute name="src">http://chocolatey.org/api/v2/package/<xsl:value-of select="p:id"/>/<xsl:value-of select="p:version"/></xsl:attribute>
          </xsl:element>
        </xsl:element>
        <m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
          <d:Version><xsl:value-of select="p:version"/></d:Version>
          <d:Copyright><xsl:value-of select="p:copyright"/></d:Copyright>
          <!--
          <d:Created m:type="Edm.DateTime"></d:Created>
          <d:Dependencies></d:Dependencies>
          -->
          <d:Description><xsl:value-of select="p:description"/></d:Description>
          <!--
          <d:DownloadCount m:type="Edm.Int32"></d:DownloadCount>
          -->
          <d:GalleryDetailsUrl>http://gallery-host/packages/<xsl:value-of select="p:id"/>/<xsl:value-of select="p:version"/></d:GalleryDetailsUrl>
          <d:IconUrl><xsl:value-of select="p:iconUrl"/></d:IconUrl>
          <!--
          <d:IsLatestVersion m:type="Edm.Boolean"></d:IsLatestVersion>
          <d:IsAbsoluteLatestVersion m:type="Edm.Boolean"></d:IsAbsoluteLatestVersion>
          <d:IsPrerelease m:type="Edm.Boolean"></d:IsPrerelease>
          <d:Language m:null="true"></d:Language>
          <d:Published m:type="Edm.DateTime"></d:Published>
          -->
          <d:LicenseUrl><xsl:value-of select="p:licenseUrl"/></d:LicenseUrl>
          <!--
          <d:PackageHash></d:PackageHash>
          <d:PackageHashAlgorithm></d:PackageHashAlgorithm>
          <d:PackageSize m:type="Edm.Int64"></d:PackageSize>
          -->
          <d:ProjectUrl><xsl:value-of select="p:projectUrl"/></d:ProjectUrl>
          <!--
          <d:ProjectSourceUrl m:null="true"></d:ProjectSourceUrl>
          <d:PackageSourceUrl m:null="true"></d:PackageSourceUrl>
          <d:DocsUrl m:null="true"></d:DocsUrl>
          <d:MailingListUrl m:null="true"></d:MailingListUrl>
          <d:BugTrackerUrl m:null="true"></d:BugTrackerUrl>
          -->
          <d:ReportAbuseUrl>http://gallery-host/package/ReportAbuse/<xsl:value-of select="p:id"/>/<xsl:value-of select="p:version"/></d:ReportAbuseUrl>
          <d:ReleaseNotes><xsl:value-of select="p:releaseNotes"/></d:ReleaseNotes>
          <!--
          <d:PackageStatus></d:PackageStatus>
          <d:PackageSubmittedStatus m:null="true"></d:PackageSubmittedStatus>
          <d:RequireLicenseAcceptance m:type="Edm.Boolean"></d:RequireLicenseAcceptance>
          -->
          <d:Tags xml:space="preserve"><xsl:value-of select="p:tags"/></d:Tags>
          <d:Title><xsl:value-of select="p:title"/></d:Title>
          <!--
          <d:VersionDownloadCount m:type="Edm.Int32"></d:VersionDownloadCount>
          -->
        </m:properties>
      </xsl:for-each>
      <xsl:for-each select="p:package/p:metadata" xmlns:p="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
        <xsl:element name="entry">
          <xsl:element name="id"><xsl:value-of select="p:id"/></xsl:element>
          <xsl:element name="title">
            <xsl:attribute name="type">text</xsl:attribute>
            <xsl:value-of select="p:title"/>
          </xsl:element>
          <xsl:element name="summary">
            <xsl:attribute name="type">text</xsl:attribute>
            <xsl:value-of select="p:summary"/></xsl:element>
          <xsl:element name="author">
            <xsl:element name="name"><xsl:value-of select="p:authors"/></xsl:element>
          </xsl:element>
          <xsl:element name="link">
            <xsl:attribute name="rel">edit-media</xsl:attribute>
            <xsl:attribute name="title">V2FeedPackage</xsl:attribute>
            <xsl:attribute name="href">Packages(Id='<xsl:value-of select="p:id"/>',Version='<xsl:value-of select="p:version"/>')/$value</xsl:attribute>
          </xsl:element>
          <xsl:element name="link">
            <xsl:attribute name="rel">edit</xsl:attribute>
            <xsl:attribute name="title">V2FeedPackage</xsl:attribute>
            <xsl:attribute name="href">Packages(Id='<xsl:value-of select="p:id"/>',Version='<xsl:value-of select="p:version"/>')</xsl:attribute>
          </xsl:element>
          <xsl:element name="category">
            <xsl:attribute name="term">NuGetGallery.V2FeedPackage</xsl:attribute>
            <xsl:attribute name="scheme">http://schemas.microsoft.com/ado/2007/08/dataservices/scheme</xsl:attribute>
          </xsl:element>
          <xsl:element name="content">
            <xsl:attribute name="type">application/zip</xsl:attribute>
            <xsl:attribute name="src">http://chocolatey.org/api/v2/package/<xsl:value-of select="p:id"/>/<xsl:value-of select="p:version"/></xsl:attribute>
          </xsl:element>
        </xsl:element>
        <m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
          <d:Version><xsl:value-of select="p:version"/></d:Version>
          <d:Copyright><xsl:value-of select="p:copyright"/></d:Copyright>
          <!--
          <d:Created m:type="Edm.DateTime"></d:Created>
          <d:Dependencies></d:Dependencies>
          -->
          <d:Description><xsl:value-of select="p:description"/></d:Description>
          <!--
          <d:DownloadCount m:type="Edm.Int32"></d:DownloadCount>
          -->
          <d:GalleryDetailsUrl>http://gallery-host/packages/<xsl:value-of select="p:id"/>/<xsl:value-of select="p:version"/></d:GalleryDetailsUrl>
          <d:IconUrl><xsl:value-of select="p:iconUrl"/></d:IconUrl>
          <!--
          <d:IsLatestVersion m:type="Edm.Boolean"></d:IsLatestVersion>
          <d:IsAbsoluteLatestVersion m:type="Edm.Boolean"></d:IsAbsoluteLatestVersion>
          <d:IsPrerelease m:type="Edm.Boolean"></d:IsPrerelease>
          <d:Language m:null="true"></d:Language>
          <d:Published m:type="Edm.DateTime"></d:Published>
          -->
          <d:LicenseUrl><xsl:value-of select="p:licenseUrl"/></d:LicenseUrl>
          <!--
          <d:PackageHash></d:PackageHash>
          <d:PackageHashAlgorithm></d:PackageHashAlgorithm>
          <d:PackageSize m:type="Edm.Int64"></d:PackageSize>
          -->
          <d:ProjectUrl><xsl:value-of select="p:projectUrl"/></d:ProjectUrl>
          <!--
          <d:ProjectSourceUrl m:null="true"></d:ProjectSourceUrl>
          <d:PackageSourceUrl m:null="true"></d:PackageSourceUrl>
          <d:DocsUrl m:null="true"></d:DocsUrl>
          <d:MailingListUrl m:null="true"></d:MailingListUrl>
          <d:BugTrackerUrl m:null="true"></d:BugTrackerUrl>
          -->
          <d:ReportAbuseUrl>http://gallery-host/package/ReportAbuse/<xsl:value-of select="p:id"/>/<xsl:value-of select="p:version"/></d:ReportAbuseUrl>
          <d:ReleaseNotes><xsl:value-of select="p:releaseNotes"/></d:ReleaseNotes>
          <!--
          <d:PackageStatus></d:PackageStatus>
          <d:PackageSubmittedStatus m:null="true"></d:PackageSubmittedStatus>
          <d:RequireLicenseAcceptance m:type="Edm.Boolean"></d:RequireLicenseAcceptance>
          -->
          <d:Tags xml:space="preserve"><xsl:value-of select="p:tags"/></d:Tags>
          <d:Title><xsl:value-of select="p:title"/></d:Title>
          <!--
          <d:VersionDownloadCount m:type="Edm.Int32"></d:VersionDownloadCount>
          -->
        </m:properties>
      </xsl:for-each>
    </feed>
  </xsl:template>
</xsl:stylesheet>

输出仍然包含太多feed个元素,我认为这是由于xsltproc处理通配符/多个输入文件的方式(它为每个文件运行一个单独的转换,这实际上是合乎逻辑的)。如果我可以摆脱这些,并找到一种处理多个输入命名空间的更好方法(而不是复制每个命名空间的转换代码),我将是一个快乐的兔子。

1 个答案:

答案 0 :(得分:1)

我想你要替换

  <feed xml:base="http://gallery-host/api/v2/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
    <title type="text">Packages</title>
    <id>http://gallery-host/api/v2/Packages</id>
    <updated></updated>
    <link rel="self" title="Packages" href="Packages" />
    <xsl:apply-templates />
  </feed>

<xsl:template match="/">
  <feed xml:base="http://gallery-host/api/v2/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
    <title type="text">Packages</title>
    <id>http://gallery-host/api/v2/Packages</id>
    <updated></updated>
    <link rel="self" title="Packages" href="Packages" />
    <xsl:apply-templates />
  </feed>
</xsl:template>

但是您还需要将所有名称空间声明移动到xsl:stylesheet,例如

<xsl:stylesheet xml:base="http://gallery-host/api/v2/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">...</xsl:stylesheet>