2016-09-23 37 views
1

我正在尝试使用XSL对XML文件进行排序。我对XSL相当陌生,并且编写了一个.Net应用程序将XSL应用于XML并将其保存到新文件。这工作正常。该XML的一个简化版本是这样的(细心的读者会注意到,这是一个管理Studio项目文件):如何使用XSL对XML文件的一部分进行排序

<?xml version="1.0"?> 
<SqlWorkbenchSqlProject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="PMISQL"> 
    <Items> 
    <LogicalFolder Name="Connections" Type="2" Sorted="true"> 
     <Items> 
     <ConnectionNode Name="cerberus:XPOOLE\barney.russ"> 
      <Created>2013-06-28T15:50:27.919788+01:00</Created> 
      <Type>SQL</Type> 
      <Server>cerberus</Server> 
      <UserName /> 
      <Authentication>Windows Authentication</Authentication> 
      <InitialDB>master</InitialDB> 
      <LoginTimeout>15</LoginTimeout> 
      <ExecutionTimeout>0</ExecutionTimeout> 
      <ConnectionProtocol>NotSpecified</ConnectionProtocol> 
      <ApplicationName>Microsoft SQL Server Management Studio - Query</ApplicationName> 
     </ConnectionNode> 
     </Items> 
    </LogicalFolder> 
    <LogicalFolder Name="Queries" Type="0" Sorted="true"> 
     <Items> 
     <FileNode Name="PMI193_Documents.sql"> 
      <AssociatedConnectionMoniker>8c91a03d-f9b4-46c0-a305-b5dcc79ff907:tyro:True</AssociatedConnectionMoniker> 
      <AssociatedConnSrvName>tyro</AssociatedConnSrvName> 
      <AssociatedConnUserName /> 
      <FullPath>PMI193_Documents.sql</FullPath> 
     </FileNode> 
     <FileNode Name="PMI002_EventTypes.sql"> 
      <AssociatedConnectionMoniker>8c91a03d-f9b4-46c0-a305-b5dcc79ff907:cerberus:True</AssociatedConnectionMoniker> 
      <AssociatedConnSrvName>cerberus</AssociatedConnSrvName> 
      <AssociatedConnUserName /> 
      <FullPath>PMI002_EventTypes.sql</FullPath> 
     </FileNode> 
     <FileNode Name="PMI079a_DementiaScreeningDetail.sql"> 
      <AssociatedConnectionMoniker>8c91a03d-f9b4-46c0-a305-b5dcc79ff907:tyro:True</AssociatedConnectionMoniker> 
      <AssociatedConnSrvName>tyro</AssociatedConnSrvName> 
      <AssociatedConnUserName /> 
      <FullPath>PMI079a_DementiaScreeningDetail.sql</FullPath> 
     </FileNode> 
     </Items> 
    </LogicalFolder> 
    <LogicalFolder Name="Miscellaneous" Type="3" Sorted="true"> 
     <Items /> 
    </LogicalFolder> 
    </Items> 
    <SccProjectName>$/DataWarehouse/Dev/Reports</SccProjectName> 
    <SccAuxPath /> 
    <SccLocalPath>..</SccLocalPath> 
    <SccProvider>MSSCCI:Team Foundation Server MSSCCI Provider</SccProvider> 
</SqlWorkbenchSqlProject> 

你会注意到,有几个LogicalFolder部分。我只是感兴趣的排序属性名称=“查询”,我希望它由子元素Items/FileNode/FullPath排序。

我已经采取了一些XSL这是身份XSL并扩展它。它会复制原始文件,但不会对我想要的部分进行排序(事实上,它似乎没有排序)。该XSL我创建看起来像这样:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"> 

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

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

    <xsl:template match="/SqlWorkbenchSqlPro/Items/LogicalFolder/Items"> 
     <xsl:apply-templates select="."> 
      <xsl:sort select="FullPath"/> 
     </xsl:apply-templates> 
    </xsl:template> 
</xsl:stylesheet> 

我不知道如何指定我只选段/ SqlWorkbenchSqlPro /项目/ LogicalFolder /项目其中Name =“查询”感兴趣,如何指定要排序的元素级别以及如何指定使用哪个元素对项目排序。真的,我不是很擅长XSL,因为我几小时前才开始看这个。

任何帮助非常感谢。我很头疼。

回答

0

您建立在身份模板上的事实是一个很好的开始,所以您并不遥远。您遇到的第一个问题是您的模板引用了SqlWorkbenchSqlPro,但在您的XML中,它是SqlWorkbenchSqlProject,因此不匹配任何内容。

但是不要去纠正它,因为如果你这样做,你的模板会陷入循环。使用<xsl:apply-templates select=".">将只选择相同的匹配模板。你应该在这里做<xsl:apply-templates select="FileNode" />,或者只是<xsl:apply-templates />

但是,为了回答你的主要问题,你可以添加一个条件,在方括号中的目标,你想

<xsl:template match="LogicalFolder[@Name='Queries']/Items"> 

注意没有必要指定节点此处节点的完整路径。

试试这个XSLT

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"> 

    <xsl:strip-space elements="*" /> 
    <xsl:output method="xml" indent="yes"/> 

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

    <xsl:template match="LogicalFolder[@Name='Queries']/Items"> 
     <xsl:copy> 
      <xsl:apply-templates> 
       <xsl:sort select="FullPath"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

注意在Items模板使用xsl:copy,选择和排序的子节点之前,现有的Items复制元素。

0

如何指定我只选了部分LogicalFolder/Items感兴趣的地方Name="Queries"

这是非常容易的。制作模板,使其仅匹配此特定类型的节点。

<xsl:template match="LogicalFolder[@Name = 'Queries']/Items"> 
    <xsl:copy> 
     <xsl:apply-templates select="*"> 
      <xsl:sort select="FullPath" data-type="text" /> 
     </xsl:apply-templates> 
    </xsl:copy> 
</xsl:template> 

这复制了<Items>元素。之后,您不希望将模板应用于.(当前节点,即<Items>),而是应用*(其所有子元素,即<FileNode>)。

如何指定元素的哪些层面进行梳理,

这是非常容易的,太。排序适用于选定的节点。在上面的例子中,所有的子元素都被选中。这意味着订购仅限于LogicalFolder/Items下的元素的顶层。

假设有可以被嵌套<Items>,你想递归地排序,所有你需要做的是改变模板通过改变match表达像这样适用于所有节点<Items>一个LogicalFolder[@Name = 'Queries']内:

<xsl:template match="Items[ancestor::LogicalFolder[@Name = 'Queries']]"> 

不需要其他更改,XSLT处理器会为您执行递归。 (<xsl:apply-templates>是递归步骤)。

,以及如何指定要使用的物品

<xsl:sort>选择表达式总是相对于所述节点被命令进行排序,其元件。在上文中,

<xsl:apply-templates select="*"> 

选择一束<FileNode>元件,这意味着

<xsl:sort select="FullPath" data-type="text" /> 

是正确的。 (data-type,因为这是很好的做法,不是因为它是绝对必要的,text是默认值。)

相关问题