2

我正在尝试使用 xslt 生成多个 xml 文件。我的 * input.xm *l 文件是

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"     
<soapenv:Body>
 <ns1:getDocumentByKeyResponse   soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"   xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <Document xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
<Attributes>
 <Attribute name="duration">0:00:00.084</Attribute>
 <Attribute name="count">7</Attribute>
<Attribute name="entity">Requisition</Attribute>
<Attribute name="mode">XML</Attribute>
<Attribute name="version">http://www.taleo.com/ws/tee800/2009/01</Attribute>
</Attributes>
<Content>
<ExportXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <record>
<field name="ContestNumber">1300000F</field>
  <field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000H</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000T</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000018</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">000123</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000R</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000016</field>
 <field name="ManagerRequisitionTitle">Project Manager</field>
 </record>
</ExportXML>
</Content>
</Document>
</ns1:getDocumentByKeyResponse>
</soapenv:Body>
</soapenv:Envelope>

我的 xslt 是 sample.xslt

<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:param name="pDest" select="'file:///c:/temp/'"/>
<xsl:template match="*[starts-with(name(),'ExportXML')]">
<xsl:for-each select="record">
<xsl:result-document href="{$pDest}section{position()}.xml">
<JobPositionPostings>
<JobPositionPosting>
<xsl:apply-templates select="*:field[starts-with(@name,'ContestNumber')]"/>
 <JobDisplayOptions>
 <xsl:apply-templates select="*:field[starts-with(@name,'ManagerRequisitionTitle')]"/>
 </JobDisplayOptions>
</JobPositionPosting>
</JobPositionPostings>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

我没有得到正确的输出。我希望每个输入标签数据都像这样放在单独的文件中

  <?xml version="1.0" encoding="UTF-8"?>
  </JobPositionPostings>
  <JobPositionPostings>
  <JobPositionPosting>
 <contestnumber>13000016</contestnumber>
 <JobDisplayOptions>
 <managerrequisitiontitle>Project Manager</managerrequisitiontitle>
 </JobDisplayOptions>
 </JobPositionPosting>
 </JobPositionPostings>

请建议我任何解决方案。提前谢谢。

4

2 回答 2

1

下面是两个解决方案,尽管我不得不做出一些假设,因为您不清楚您的要求。第一个解决方案soap.xsl使用拉式样式,其中元素在样式表中显示。第二种解决方案soap2.xsl使用从属性名称合成元素的推送样式。在介绍完这些基础知识之后,我不知道您还想对样式表做什么。

t:\ftemp>type soap.xml 
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">     
<soapenv:Body>
 <ns1:getDocumentByKeyResponse   soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"   xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <Document xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
<Attributes>
 <Attribute name="duration">0:00:00.084</Attribute>
 <Attribute name="count">7</Attribute>
<Attribute name="entity">Requisition</Attribute>
<Attribute name="mode">XML</Attribute>
<Attribute name="version">http://www.taleo.com/ws/tee800/2009/01</Attribute>
</Attributes>
<Content>
<ExportXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <record>
<field name="ContestNumber">1300000F</field>
  <field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000H</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000T</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000018</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">000123</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000R</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000016</field>
 <field name="ManagerRequisitionTitle">Project Manager</field>
 </record>
</ExportXML>
</Content>
</Document>
</ns1:getDocumentByKeyResponse>
</soapenv:Body>
</soapenv:Envelope>
t:\ftemp>rmdir /s /q temp 

t:\ftemp>call xslt2 soap.xml soap.xsl 

t:\ftemp>type temp\section1.xml 
<JobPositionPostings>
   <JobPositionPosting>
      <contestnumber>1300000F</contestnumber>
      <JobDisplayOptions>
         <managerrequisitiontitle>Project Manager</managerrequisitiontitle>
      </JobDisplayOptions>
   </JobPositionPosting>
</JobPositionPostings>

t:\ftemp>dir temp 
 Volume in drive T is VBOX_t
 Volume Serial Number is 0E00-0001

 Directory of t:\ftemp\temp

2013-08-11  17:00               269 section1.xml
2013-08-11  17:00               269 section2.xml
2013-08-11  17:00               269 section3.xml
2013-08-11  17:00               269 section4.xml
2013-08-11  17:00               267 section5.xml
2013-08-11  17:00               269 section6.xml
2013-08-11  17:00               269 section7.xml
               7 File(s)          1,881 bytes
               0 Dir(s)   8,351,150,080 bytes free

t:\ftemp>type soap.xsl 
<xsl:stylesheet version="2.0"
  xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:param name="pDest" select="'temp/'"/>

<xsl:template match="/">
  <xsl:for-each select="//record">
    <xsl:result-document href="{$pDest}section{position()}.xml">
      <JobPositionPostings>
        <JobPositionPosting>
          <contestnumber>
            <xsl:value-of select="field[@name='ContestNumber']"/>
          </contestnumber>
          <JobDisplayOptions>
            <managerrequisitiontitle>
              <xsl:value-of select="field[@name='ManagerRequisitionTitle']"/>
            </managerrequisitiontitle>
          </JobDisplayOptions>
        </JobPositionPosting>
      </JobPositionPostings>
    </xsl:result-document>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rmdir /s /q temp 

t:\ftemp>call xslt2 soap.xml soap2.xsl 

t:\ftemp>type temp\section2.xml 
<JobPositionPostings>
   <JobPositionPosting>
      <contestnumber>1300000H</contestnumber>
      <JobDisplayOptions>
         <managerrequisitiontitle>Project Manager</managerrequisitiontitle>
      </JobDisplayOptions>
   </JobPositionPosting>
</JobPositionPostings>

t:\ftemp>dir temp 
 Volume in drive T is VBOX_t
 Volume Serial Number is 0E00-0001

 Directory of t:\ftemp\temp

2013-08-11  17:00               269 section1.xml
2013-08-11  17:00               269 section2.xml
2013-08-11  17:00               269 section3.xml
2013-08-11  17:00               269 section4.xml
2013-08-11  17:00               267 section5.xml
2013-08-11  17:00               269 section6.xml
2013-08-11  17:00               269 section7.xml
               7 File(s)          1,881 bytes
               0 Dir(s)   8,351,670,272 bytes free

t:\ftemp>type soap2.xsl 
<xsl:stylesheet version="2.0" 
  xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:param name="pDest" select="'temp/'"/>

<xsl:template match="/">
  <xsl:for-each select="//record">
    <xsl:result-document href="{$pDest}section{position()}.xml">
      <JobPositionPostings>
        <JobPositionPosting>
          <xsl:apply-templates select="field[@name='ContestNumber']"/>
          <JobDisplayOptions>
            <xsl:apply-templates
                     select="field[@name='ManagerRequisitionTitle']"/>
          </JobDisplayOptions>
        </JobPositionPosting>
      </JobPositionPostings>
    </xsl:result-document>
  </xsl:for-each>
</xsl:template>

<xsl:template match="field">
  <xsl:element name="{lower-case(@name)}">
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done! 
于 2013-08-11T21:01:07.467 回答
0

您的 XSLT 有几个问题,主要是关于名称空间。您从以下模板匹配开始

<xsl:template match="*[starts-with(name(),'ExportXML')]">

这很好,但只有在您知道ExportXML元素属于命名空间(在您的情况下属于)但不知道命名空间将是什么时,您才真正需要这样做。不过,理想情况下,您应该在这里使用“local-name()”,而不是“name()”,因为 name() 将包含任何命名空间前缀,因此在以下情况下不起作用。

<x:ExportXML xmlns:x="http://www.taleo.com/ws/integration/toolkit/2005/07">

无论如何,问题出现在您的下一行 XSLT

<xsl:for-each select="record">

当您的 XML 中的记录元素与ExportXML属于同一名称空间(与其所有后代一样)时,这是在寻找不属于任何名称空间的记录元素。您应该在这里使用类似的语法(假设您真的事先不知道命名空间)

<xsl:for-each select="*[starts-with(local-name(),'record')]">

下一个问题是用于获取“ContestNumber”(和“ManagerRequisitionTitle”)值的代码:

<xsl:apply-templates select="*:field[starts-with(@name,'ContestNumber')]"/>

除了在语法上无效之外,字段元素也在命名空间中也存在相同的问题,因此您需要这样做

<xsl:apply-templates select="*[starts-with(local-name(), 'field')][@name='ContestNumber']"/>

虽然这里可能不需要使用xsl:apply-templates ,但应该使用xsl:value-of

试试这个 XSLT

<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:param name="pDest" select="'file:///c:/temp/'"/>
   <xsl:template match="*[starts-with(local-name(),'ExportXML')]">
      <xsl:for-each select="*[starts-with(local-name(),'record')]">
         <xsl:result-document href="{$pDest}section{position()}.xml">
            <JobPositionPostings>
               <JobPositionPosting>
                  <xsl:value-of select="*[starts-with(local-name(), 'field')][@name='ContestNumber']"/>
                  <JobDisplayOptions>
                     <xsl:value-of select="*[starts-with(local-name(), 'field')][@name='ManagerRequisitionTitle']"/>
                  </JobDisplayOptions>
               </JobPositionPosting>
            </JobPositionPostings>
         </xsl:result-document>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="*[starts-with(local-name(), 'Attributes')]"/>
</xsl:stylesheet>

还要注意要匹配的模板,并忽略属性,否则 XSLT 的内置模板将匹配这些,并输出文本值。

当然,如果您现在这样做,命名空间总是相同的,您可以通过声明命名空间来简化您的 XSLT。这个 XSLT 也应该可以工作:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07">
   <xsl:output omit-xml-declaration="yes" indent="yes"/>
   <xsl:strip-space elements="*"/>
   <xsl:param name="pDest" select="'file:///c:/temp/'"/>
   <xsl:template match="ExportXML">
      <xsl:for-each select="record">
         <xsl:result-document href="{$pDest}section{position()}.xml">
            <JobPositionPostings>
               <JobPositionPosting>
                  <xsl:value-of select="field[@name='ContestNumber']"/>
                  <JobDisplayOptions>
                     <xsl:value-of select="field[@name='ManagerRequisitionTitle']"/>
                  </JobDisplayOptions>
               </JobPositionPosting>
            </JobPositionPostings>
         </xsl:result-document>
      </xsl:for-each>
   </xsl:template>
   <xsl:template match="Attributes"/>
</xsl:stylesheet>

编辑:测试模板匹配的一种方法是临时将 XSLT 更改为不使用xsl:result-document。相反,将其更改为此时输出一个普通元素

<!-- <xsl:result-document href="{$pDest}section{position()}.xml"> -->
<file href="{$pDest}section{position()}.xml">
   <JobPositionPostings>...</JobPositionPostings>
</file>

然后,使用 XSLT 测试工具(例如http://xslttest.appspot.com/)并测试您的 XML 和修改后的 XSLT,以查看是否正在创建多个文件元素。如果是这样,您应该能够改回使用xsl:result-document

于 2013-08-11T21:01:44.713 回答