libxml2-xpath和更新属性

时间:2018-07-26 16:25:17

标签: c xml libxml2

我有两个xml文件A和B,它们具有相同的架构。

A.xml

<books>
    <book name="Alice in Wonderland" />
</books>

B.xml

<books>
    <book name="Of Mice and Men" />
    <book name="Harry Potter" />
</books>

我想在B.xml中的书籍列表中添加属性source =“ B”,然后将该列表复制到A.xml中,以便A.xml看起来像这样

<books>
    <book name="Alice in Wonderland" />
    <book name="Of Mice and Men" source="B" />
    <book name="Harry Potter" source="B" />
</books>

我可以使用xpath从B获取书籍的xpath对象,添加属性,然后将节点集复制到A吗?如果是这样,代码将如何显示?是否有比xpath更好的方法来从B处获取书籍?

1 个答案:

答案 0 :(得分:1)

我想最简单的方法是使用XSLT处理器。对于此任务,XSLT-1.0处理器就足够了。您可以使用以下模板“合并”两个文件。只需将XSLT处理器与参数a.xslta.xml一起使用。第二个文件名在a.xslt中指定。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
  <!-- This is the base filename of the second file without the extension '.xml' -->      
  <xsl:variable name="secondXMLFile" select="'b'" />    
  <!-- This changes the second filename to uppercase -->   
  <xsl:variable name="secondName" select="translate($secondXMLFile,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />    
  <!-- This adds the filename extension '.xml' to the base filename and creates a document() node -->                                     
  <xsl:variable name="second" select="document(concat($secondXMLFile,'.xml'))" />            

  <!-- identity template -->                     <!-- This copies all elements from the first file -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
   </xsl:template>  

  <!-- modified identity template for second/other document -->  
  <xsl:template match="*" mode="sec">            <!-- This copies all 'book' elements from the second file -->
    <xsl:element name="{name()}">
      <xsl:apply-templates select="@*" />
      <xsl:attribute name="source"><xsl:value-of select="$secondName" /></xsl:attribute>
      <xsl:apply-templates select="node()" />     
    </xsl:element>
  </xsl:template>  

   <xsl:template match="/books">                 <!-- This initiates the copying of both files -->
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
        <xsl:apply-templates select="$second/books/*" mode="sec" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>