使用XPATH和XSLT基于属性值上的某些相等条件,在XML中提取相关的不同元素标记

时间:2012-10-19 18:26:25

标签: xml xslt xpath xslt-2.0 break

我需要使用XPATH和XSLT以某种特定方式从XML中提取数据

<data>      
    <person id="p1">         
        <name>User1</name>      
    </person>   
    <person id="p2">         
        <name>User2</name>      
    </person>  
    <person id="p3">         
        <name>User3</name>      
    </person>       
    <employee eid="emp1" pid="p1">         
        <dept>dept1</dept>      
    </employee> 
    <employee eid="emp2" pid="p3">         
        <dept>dept3</dept>      
    </employee>
    <employee eid="emp3" pid="p2">         
        <dept>dept1</dept>      
    </employee>
</data>

从上面的例子中,我需要创建每个包含Person的XML以及输出xml中相应的Employee元素。这两个xmls之间的链接是

person.id = employee.pid

像 XML1:

<person id="p1">         
<name>User1</name>      
</person>  
<employee eid="emp1" pid="p1">         
<dept>dept1</dept>      
</employee>

XML2:

<person id="p2">         
<name>User2</name>      
</person> 
<employee eid="emp3" pid="p2">         
 <dept>dept1</dept>      
</employee>

XML3:

<person id="p3">         
<name>User3</name>      
</person> 
<employee eid="emp2" pid="p3">         
<dept>dept3</dept>      
</employee>  

我尝试了很多方法但却无法得到这个。

...谢谢

2 个答案:

答案 0 :(得分:2)

XPath是XML文档的查询语言 - 因此评估XPath表达式无法修改现有文档或创建新的XML文档

使用XSLT 2.0(XSLT 1.0,如果只需要一个结果文档)可以最好地实现您的目标:

<xsl:stylesheet version="2.0"   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="kEmpByPid" match="employee" use="@pid"/>

 <xsl:template match="person">
  <xsl:result-document href="file:///c:/temp/delete/XML{position()}">
      <t>
             <xsl:copy-of select=".|key('kEmpByPid', @id)"/>
         </t>
     </xsl:result-document>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

在提供的XML文档上应用此XSLT 2.0转换时:

<data>
    <person id="p1">
        <name>User1</name>
    </person>
    <person id="p2">
        <name>User2</name>
    </person>
    <person id="p3">
        <name>User3</name>
    </person>
    <employee eid="emp1" pid="p1">
        <dept>dept1</dept>
    </employee>
    <employee eid="emp2" pid="p3">
        <dept>dept3</dept>
    </employee>
    <employee eid="emp3" pid="p2">
        <dept>dept1</dept>
    </employee>
</data>

在“c:\ temp \ delete”:

中创建以下三个XML文档

<强> XML1

<t>
   <person id="p1">
      <name>User1</name>
   </person>
   <employee eid="emp1" pid="p1">
      <dept>dept1</dept>
   </employee>
</t>

<强> XML2

<t>
   <person id="p2">
      <name>User2</name>
   </person>
   <employee eid="emp3" pid="p2">
      <dept>dept1</dept>
   </employee>
</t>

<强> XML3

<t>
   <person id="p3">
      <name>User3</name>
   </person>
   <employee eid="emp2" pid="p3">
      <dept>dept3</dept>
   </employee>
</t>

答案 1 :(得分:0)

我已经为上面的问题找到了以下解决方案。

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:template match="//person">
        <xsl:variable name="ID" select="@id" />
        <xsl:result-document href="file:///c:/temp/delete/XML{position()}">
        <t>
            <xsl:copy-of select=". | //employee[@pid=$ID]" />
        </t>                
        </xsl:result-document>
    </xsl:template>
    <xsl:template match="text()" />
</xsl:stylesheet>

只是想和你分享。

感谢。