2016-09-23 32 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是默認值。)

相關問題