2016-09-19 131 views
0

我有一个xpaths的源和目标列表,其中每个列表都基于他们自己的模式。对于每个源路径都存在一个目标路径。例如,我有源列表[/ shiporder/shipfrom/name,/ shiporder/address/city]和目录列表[/ root/Seller/Country],其中列表的顺序连接源与目标路径的路径。现在我可以创建简单易读的样式表,它应用每个源路径并针对目标路径创建输出。对于/运送订单/ shipfrom /名称stylesheet是:通过xpath列表创建xml文件

<xsl:template match="/"> 
     <xsl:apply-templates select="shiporder"/> 
    </xsl:template> 
<xsl:template match="/shiporder"> 
<root> 
     <xsl:apply-templates select="shipfrom"/> 
</root> 
</xsl:template> 
<xsl:template match="/shiporder/shipfrom"> 
    <Seller> 
     <xsl:apply-templates select="name"/> 
    </Seller> 
</xsl:template> 
<xsl:template match="/shiporder/shipfrom/name"> 
    <Country> 
     <xsl:apply-templates select="text()"/> 
    </Country> 
</xsl:template> 

/shiporder/address/citystylesheet是:

<xsl:template match="/"> 
     <xsl:apply-templates select="shiporder"/> 
    </xsl:template> 
<xsl:template match="/shiporder"> 
<root> 
     <xsl:apply-templates select="address"/> 
</root> 
</xsl:template> 
<xsl:template match="/shiporder/address"> 
    <Seller> 
     <xsl:apply-templates select="city"/>   
    </Seller> 
</xsl:template> 
<xsl:template match="/shiporder/address/city"> 
    <City> 
     <xsl:apply-templates select="text()"/> 
    </City> 
</xsl:template> 

创作后,我上的任意源XML文件同时应用样式基于源模式如:

<shiporder> 
    <shipfrom> 
    <name>orderperson1</name> 
    </shipfrom> 
    <address> 
    <city>London</city> 
    </address> 
    <address> 
    <city>Berlin</city> 
    </address> 
</shiporder> 

现在我喜欢将两个样式表尽可能简单地组合到一个stylesheet

+2

对不起,你的问题不是很清楚。请显示两个不同的XML输入和每个输入的期望输出。 –

+0

@JimGarrison我试图简化我的问题,让我知道如果有什么不清楚。如果你对标题有更好的建议,也请告诉我。 – StellaMaris

+0

如果所有元素都存在,您的预期输出是什么?如在你的示例输入XML中一样? –

回答

0

从我在你的问题理解的基础,我想出了这样的事情:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

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

    <xsl:template match="shiporder"> 
     <root> 
      <xsl:apply-templates/> 
     </root> 
    </xsl:template> 

    <xsl:template match="address"> 
     <!-- store the name node to a variable --> 
     <xsl:variable name="country" select="../shipfrom/name"/> 
     <Seller> 
      <xsl:apply-templates/> 
      <!-- check if the variable is not empty, 
       if not, output the contents under the node Country --> 
      <xsl:if test="normalize-space($country)!=''"> 
       <Country> 
        <xsl:value-of select="$country"/> 
       </Country> 
      </xsl:if> 
     </Seller> 
    </xsl:template> 

    <xsl:template match="city"> 
     <City> 
      <xsl:apply-templates/> 
     </City> 
    </xsl:template> 

    <xsl:template match="shipfrom"> 
     <xsl:choose> 
      <!-- check for following-sibling address nodes, 
       if none found, delete the node --> 
      <xsl:when test="following-sibling::address"/> 
      <xsl:otherwise> 
       <Seller> 
        <xsl:apply-templates/> 
       </Seller> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <xsl:template match="shipfrom/name"> 
     <Country> 
      <xsl:apply-templates/> 
     </Country> 
    </xsl:template> 

</xsl:stylesheet> 
0

你的第一个样式表输出下面的XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <Seller> 
     <Country>orderperson1</Country> 
    </Seller> 
</root> 

而且你的第二个样式表输出如下因素XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <Seller> 
     <City>London</City> 
    </Seller> 
    <Seller> 
     <City>Berlin</City> 
    </Seller> 
</root> 

如果要生成两个输出结果b在一个样式表模块中,您应该引入控制输出的参数xsl:param。我制作了实现此要求的最小样式表。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:param name="prmOutputShipForm" select="'yes'"/> 
    <xsl:variable name="pOutputShipForm" select="$prmOutputShipForm = 'yes'"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="shiporder"/> 
    </xsl:template> 

    <xsl:template match="/shiporder"> 
     <root> 
      <xsl:choose> 
       <xsl:when test="$pOutputShipForm"> 
        <xsl:apply-templates select="shipfrom"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:apply-templates select="address"/> 
       </xsl:otherwise> 
      </xsl:choose> 
     </root> 
    </xsl:template> 

    <xsl:template match="/shiporder/shipfrom"> 
     <Seller> 
      <xsl:apply-templates select="name"/> 
     </Seller> 
    </xsl:template> 

    <xsl:template match="/shiporder/shipfrom/name"> 
     <Country> 
      <xsl:apply-templates/> 
     </Country> 
    </xsl:template> 

    <xsl:template match="/shiporder/address"> 
     <Seller> 
      <xsl:apply-templates select="city"/>   
     </Seller> 
    </xsl:template> 

    <xsl:template match="/shiporder/address/city"> 
     <City> 
      <xsl:apply-templates/> 
     </City> 
    </xsl:template> 

</xsl:stylesheet> 

通过设置OutputShipForm =“yes/no”,可以控制输出XML结果。

+0

Thx tmakita,但它正在寻找别的东西,因为假设我有一个第三''/ shiporder/elem3/xy'和第四''/ shiporder/elem4/xy'元素,我想以相同的方式添加分支变得复杂。 – StellaMaris

+0

@StellaMaris您能指定想要处理的具体输入XML文件吗?我认为上面的样式表修改至少适用于您的输入XML示例。 – tmakita

+0

源xml文件可以是任意的,你至少会找到根节点'shiporder'。在源列表中以xpath形式给出的所有其他元素不是必需的,但可能会在源xml中找到它们。 – StellaMaris