2013-03-05 46 views
1

考慮下面的XML文檔:解析XML文檔轉換成單獨的XPath沒有文件預知

<Element0 AttributeA="A"> 
    <Element1 AttributeB="1" AttributeC="C" AttributeD="D"> 
    <Element2>nodeValue</Element2> 
    </Element1> 
    <Element1 AttributeB="2" AttributeC="C" AttributeD="D"> 
    <Element2>nodeValue</Element2> 
    <Element3 AttributeE="E"> 
     <Element4 AttributeF="F">nodeValue</Element4> 
    </Element3> 
    </Element1> 
    . 
    . 
    . 
    . 
</Element0> 

如何解析(切絲,去構建,翻譯)將文檔分成單獨的XPath(見下文)預知xml文檔的內容?

//Element0[@AttributeA='A']/Element1[@AttributeB='1' and @AttributeC='C' and @AttributeD='D']/Element2 
//Element0[@AttributeA='A']/Element1[@AttributeB='2' and @AttributeC='C' and @AttributeD='D']/Element2 
//Element0[@AttributeA='A']/Element1[@AttributeB='2' and @AttributeC='C' and @AttributeD='D']/Element3[@AttributeE='E']/Element4[@AttributeF='F'] 

回答

1

這是我該怎麼做。請注意,我還包括位置,以便爲每個元素獲得完全獨特的XPath,即使它具有與其中一個兄弟節點完全相同的屬性。

XML輸入

<Element0 AttributeA="A"> 
    <Element1 AttributeB="1" AttributeC="C" AttributeD="D"> 
     <Element2>nodeValue</Element2> 
    </Element1> 
    <Element1 AttributeB="2" AttributeC="C" AttributeD="D"> 
     <Element2>nodeValue</Element2> 
     <Element3 AttributeE="E"> 
      <Element4 AttributeF="F">nodeValue</Element4> 
     </Element3> 
    </Element1> 
</Element0> 

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="text()"/> 

    <xsl:template match="*"> 
     <xsl:for-each select="ancestor-or-self::*"> 
      <xsl:value-of select="concat('/',local-name())"/> 
      <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/> 
      <xsl:if test="@*"> 
       <xsl:text>[</xsl:text> 
       <xsl:apply-templates select="@*"/> 
       <xsl:text>]</xsl:text> 
      </xsl:if> 
     </xsl:for-each> 
     <xsl:text>&#xA;</xsl:text> 
     <xsl:apply-templates select="node()"/> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:if test="position() != 1"> 
      <xsl:text> and </xsl:text> 
     </xsl:if> 
     <xsl:value-of select="concat('@',local-name(),'=&quot;',.,'&quot;')"/> 
    </xsl:template> 

</xsl:stylesheet> 

輸出

/Element0[1][@AttributeA="A"] 
/Element0[1][@AttributeA="A"]/Element1[1][@AttributeB="1" and @AttributeC="C" and @AttributeD="D"] 
/Element0[1][@AttributeA="A"]/Element1[1][@AttributeB="1" and @AttributeC="C" and @AttributeD="D"]/Element2[1] 
/Element0[1][@AttributeA="A"]/Element1[2][@AttributeB="2" and @AttributeC="C" and @AttributeD="D"] 
/Element0[1][@AttributeA="A"]/Element1[2][@AttributeB="2" and @AttributeC="C" and @AttributeD="D"]/Element2[1] 
/Element0[1][@AttributeA="A"]/Element1[2][@AttributeB="2" and @AttributeC="C" and @AttributeD="D"]/Element3[1][@AttributeE="E"] 
/Element0[1][@AttributeA="A"]/Element1[2][@AttributeB="2" and @AttributeC="C" and @AttributeD="D"]/Element3[1][@AttributeE="E"]/Element4[1][@AttributeF="F"] 
+0

簡單,直接,快速......併成功!正是我需要的(包括你的位置)。謝謝@ Daniel-Haley! – EngineeringSQL 2013-03-05 03:47:52

+0

@echoScout - 不客氣! – 2013-03-05 04:49:39

0

XMLStarlet確實非常相似,如果你把它當作xml el -v file.xml東西。它會給你帶有值的路徑和屬性。但是,它不會在路徑中間給出屬性,就在該節點爲小費時。對於你的例子,它產生:

Element0[@AttributeA='A'] 
Element0/Element1[@AttributeB='1' and @AttributeC='C' and @AttributeD='D'] 
Element0/Element1/Element2 
Element0/Element1[@AttributeB='2' and @AttributeC='C' and @AttributeD='D'] 
Element0/Element1/Element2 
Element0/Element1/Element3[@AttributeE='E'] 
Element0/Element1/Element3/Element4[@AttributeF='F'] 
+0

謝謝亞歷山大你的迴應。我已經跟丹尼爾的方法走了。 – EngineeringSQL 2013-03-05 04:00:06