0
votes

Suppose I have the following identical data structure in multiple XML files...

<project>
  <property name="A" value="a"/>
  <property name="B" value="b"/>
</project>

and those files I cannot modify (ant files). Constraint #1.

And I also have an XML file referencing these files...

<files>
  <file name="file1.xml"/>
  <file name="file2.xml"/>
  <file name="file3.xml"/>
</files>

I need an XSL example that will not only combine the files, but will inject source names and allow a query simular to...

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="text"/>
  <xsl:template match="/project">
    <xsl:for-each select="property[contains(@name,'doxy')]">
      <xsl:sort select="./@name"/>
      <xsl:value-of select="./@name"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:transform>

... which would give me a simple text list of names, but I would also want to know which file the data is coming from like...

propertyname|sourcefile

So my output would look like:

A|file1.xml
B|file1.xml
C|file2.xml
D|file3.xml

I am new at XSL, and the posts I have found on SO that describe how to combine XML data do not show how to inject this sort of source file info. Is this possible to do in a single step (without a write) given the constraints I have? I am using Saxon HE XSLT processor.

1

1 Answers

2
votes

Use the file listing the other files as the main input to XSLT, then use

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:apply-templates select="document(files/file/@name)/*"/>
  </xsl:template>
  <xsl:template match="/project">
    <xsl:for-each select="property[contains(@name,'doxy')]">
      <xsl:sort select="./@name"/>
      <xsl:value-of select="concat(@name, '|', tokenize(document-uri(/), '/')[last()])"/>
      <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:transform>