1

I have two files. There is some overlap in data but I want to pull specific info from file2 and add to file1.

File1.xml looks as such:

<content>
  <book>
    <id>111aaa</id>
    <author>John Doe</author>
    <title>This is a book</title>
    <price>$10.00</price>
  </book>
  <book>
    <id>111bbb</id>
    <author>Jane Doe</author>
    <title>This is another book</title>
    <price>$20.00</price>
  </book>
</content>

File2.xml looks as such:

<content>
  <book>
    <id>111aaa</id>
    <author>John Doe</author>
    <year>2011</year>
    <pages>100</pages>
  </book>
  <book>
    <id>111bbb</id>
    <author>Jane Doe</author>
    <year>2010</year>
    <pages>200</pages>
  </book>
</content>

I want to pull the year and pages tags from file2 and add it to file1 and have an outputted file3.xml file that looks as such:

<content>
  <book>
    <id>111aaa</id>
    <author>John Doe</author>
    <title>This is a book</title>
    <year>2011</year>
    <pages>100</pages>
    <price>$10.00</price>
  </book>
  <book>
    <id>111bbb</id>
    <author>Jane Doe</author>
    <title>This is a another book</title>
    <year>2010</year>
    <pages>200</pages>
    <price>$20.00</price>
  </book>
</content>

I am using a command line to run xsltproc:

xsltproc transform.xsl file1.xml > file3.xml

I have the following chunk in my xsl but it is only combining the data of the first book. Do you know how to write the xsl to go through each book?

<xsl:choose>
                           <xsl:when test="document('file2.xml')/content/book/id = id">
                               <xsl:for-each select="document('file2.xml')/content/book">
                               <xsl:element name="pages">
                               <xsl:value-of select="document('file2.xml')/content/book/pages"/>
                               </xsl:element>
                               <xsl:element name="year">
                                  <xsl:value-of select="document('file2.xml')/content/book/year"/> 
                               </xsl:element>
                                   </xsl:for-each>
                           </xsl:when>
                           <xsl:otherwise></xsl:otherwise>
                       </xsl:choose>
2
  • 1
    Make sure to accept the answer that best fixes your problem. Commented Aug 31, 2011 at 17:40
  • @empo: He doesn't know what "accept an answer" means. Commented Sep 1, 2011 at 2:11

2 Answers 2

1

You're looking for something along these lines, I guess. Fixing syntax left up to you.

<xsl:for-each select="book">
  <xsl:copy>
    <xsl:apply-templates/>
    <xsl:variable name="id" select="string(id)"/>
    <xsl:for-each select="document('file2.xml')/content/book[string(id)=$id]/*">
      <xsl:apply-templates/><!-- Add in a choose here if you just want to pick out certain fields, or in the for-each above -->
    </xsl:for-each>
  </xsl:copy>
</xsl:for-each>
Sign up to request clarification or add additional context in comments.

Comments

1

Cross-references ask for using a key:

<xsl:key name="k1" match="book" use="id"/>

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

<xsl:template match="book">
  <xsl:variable name="id" select="id"/>
  <xsl:apply-templates select="@* | id | author"/>
  <xsl:for-each select="document('file2.xml')">
    <xsl:apply-templates select="key('k1', $id)/year | key('k1', $id)/pages"/>
  </xsl:for-each>
  <xsl:apply-templates select="price"/>
</xsl:template>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.