循环遍历XML节点列表,并根据另一个列表使用XSLT从第一个列表中输出属性的值

时间:2015-12-01 03:08:42

标签: xml xslt

这是我的输入XML:

<AllTitleByOrder>
  <CustProp name="Title of x CP" CPID='x'/>
  <CustProp name="Title of y CP" CPID='y'/>
  <CustProp name="Title of z CP" CPID='z'/>
</AllTitleByOrder>
<ResultSet>
  <ResultItem …>
    <Document ContentType="document" … >
      <CustomProperties>
         <CustPropItem CPID='x' value="value of x for doc"/>
      </CustomProperties>
    </Document>
    <Document ContentType="document" … >
      <CustomProperties>
         <CustPropItem CPID='x' value="value of x for doc"/>
         <CustPropItem CPID='y' value="value of y for doc"/>
         <CustPropItem CPID='z' value="value of z for doc"/>
      </CustomProperties>
    </Document>
  </ResultItem>
  <ResultItem …>
    <Document ContentType="research" … >
      <CustomProperties>
        <CustPropItem CPID='y' value="value of y for rsr"/>
      </CustomProperties>
    </Document>
  </ResultItem>
  <ResultItem>
    <Document ContentType="pleading" … >
      <CustomProperties>
        <CustPropItem CPID='z' value="value of z for pldg"/>
      </CustomProperties>
    </Document>
  </ResultItem>
</ResultSet>

我需要输出看起来像这样:

Title of x CP ---------- Title of y CP ---------- Title of z CP
value of x for doc
value of x for doc       value of y for rsr       value of z for pldg
                         value of y for rsr
                                                  value of z for pldg

我的麻烦是过滤(标题X的输出值仅为x),因为所有内容都在同一个XML标记(即Document)下。

我正在循环//AllTitleByOrder/CustProp/@CPID,但我不确定如何选择正确的值(对应于正确的标题)或只是添加空格。

2 个答案:

答案 0 :(得分:3)

假设(a)你想要一个HTML表作为结果,并且(b)你有一个格式良好的 XML文档作为输入,你可以尝试类似的东西:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="item-by-rowXcol" match="CustPropItem" use="concat(@CPID, generate-id(../..))" />

<xsl:template match="/root">
    <xsl:variable name="columns" select="AllTitleByOrder/CustProp"/>
    <table border="1">
        <thead>
            <tr>
                <xsl:for-each select="$columns">
                    <th>
                        <xsl:value-of select="@name"/>
                    </th>
                </xsl:for-each>
            </tr>
        </thead>
        <tbody>
            <xsl:for-each select="ResultSet/ResultItem/Document">
                <xsl:variable name="row-id" select="generate-id()" />
                <tr>
                    <xsl:for-each select="$columns">
                        <td>
                            <xsl:value-of select="key('item-by-rowXcol', concat(@CPID, $row-id))/@value" />
                        </td>
                    </xsl:for-each>
                </tr>
            </xsl:for-each>
        </tbody>
    </table>
</xsl:template>

</xsl:stylesheet>

应用于以下测试输入:

<强> XML

<root>
  <AllTitleByOrder>
    <CustProp name="Title of x CP" CPID="x"/>
    <CustProp name="Title of y CP" CPID="y"/>
    <CustProp name="Title of z CP" CPID="z"/>
  </AllTitleByOrder>
  <ResultSet>
    <ResultItem>
      <Document ContentType="document">
        <CustomProperties>
          <CustPropItem CPID="x" value="value of x for doc"/>
        </CustomProperties>
      </Document>
      <Document ContentType="document">
        <CustomProperties>
          <CustPropItem CPID="x" value="value of x for doc"/>
          <CustPropItem CPID="y" value="value of y for doc"/>
          <CustPropItem CPID="z" value="value of z for doc"/>
        </CustomProperties>
      </Document>
    </ResultItem>
    <ResultItem>
      <Document ContentType="research">
        <CustomProperties>
          <CustPropItem CPID="y" value="value of y for rsr"/>
        </CustomProperties>
      </Document>
    </ResultItem>
    <ResultItem>
      <Document ContentType="pleading">
        <CustomProperties>
          <CustPropItem CPID="z" value="value of z for pldg"/>
        </CustomProperties>
      </Document>
    </ResultItem>
  </ResultSet>
</root>

结果(渲染)将是:

enter image description here

答案 1 :(得分:0)

此XSLT 2.0样式表...

<xsl:transform
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:output method="text" encoding="UTF-8" />
<xsl:strip-space elements="*" />
<xsl:variable name="new-line" select="'&#x0A;&#x0D;'
   (: Adjust as required for your file-system. :)" />

<xsl:template match="/*">
  <!-- Do the header line. -->
  <xsl:value-of select="AllTitleByOrder/CustProp/@name" separator="," />
  <xsl:value-of select="$new-line" />

  <!-- Now the data rows. -->
  <xsl:apply-templates select="ResultSet/ResultItem/Document" />
</xsl:template>

<xsl:template match="Document">
  <xsl:value-of select="
    for $ID in ../../../AllTitleByOrder/CustProp/@CPID
      return concat( CustomProperties/CustPropItem[@CPID eq $ID]/@value, '')"
    separator="," />
  <xsl:value-of select="$new-line" />
</xsl:template>

</xsl:transform>

...应用于此输入文档时...

<root>
<AllTitleByOrder>
  <CustProp name="Title of x CP" CPID='x'/>
  <CustProp name="Title of y CP" CPID='y'/>
  <CustProp name="Title of z CP" CPID='z'/>
</AllTitleByOrder>
<ResultSet>
  <ResultItem>
    <Document ContentType="document">
      <CustomProperties>
         <CustPropItem CPID='x' value="value of x for doc"/>
      </CustomProperties>
    </Document>
    <Document ContentType="document">
      <CustomProperties>
         <CustPropItem CPID='x' value="value of x for doc"/>
         <CustPropItem CPID='y' value="value of y for doc"/>
         <CustPropItem CPID='z' value="value of z for doc"/>
      </CustomProperties>
    </Document>
  </ResultItem>
  <ResultItem>
    <Document ContentType="research">
      <CustomProperties>
        <CustPropItem CPID='y' value="value of y for rsr"/>
      </CustomProperties>
    </Document>
  </ResultItem>
  <ResultItem>
    <Document ContentType="pleading">
      <CustomProperties>
        <CustPropItem CPID='z' value="value of z for pldg"/>
      </CustomProperties>
    </Document>
  </ResultItem>
</ResultSet>
</root>

...将产生此csv输出文档......

Title of x CP,Title of y CP,Title of z CP
value of x for doc,,
value of x for doc,value of y for doc,value of z for doc
,value of y for rsr,
,,value of z for pldg

Fancy Pants One-Liner

如果你想得到所有花哨的裤子,你可以在一行XPATH中解决整个问题......

<xsl:transform
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:output method="text" encoding="UTF-8" />
<xsl:strip-space elements="*" />
<xsl:variable name="new-line" select="'&#x0A;&#x0D;'" />

<xsl:template match="/*">
  <xsl:value-of select="
    string-join( AllTitleByOrder/CustProp/@name, ','), (: Header :)
    ResultSet/ResultItem/Document/string-join(         (: Rows   :)
      for $ID in ../../../AllTitleByOrder/CustProp/@CPID
        return concat( CustomProperties/CustPropItem[@CPID eq $ID]/@value, ''),
      ',')
    " separator="{$new-line}"/>
</xsl:template>

</xsl:transform>