将XML字段与XSLT合并

时间:2015-05-25 09:31:42

标签: xml xslt

这实际上是我之前的问题的后续问题,但我已经迭代了我的问题,所以这可能更容易解决。我有以下格式的XML数据:

<v1:publications xmlns:commons="v3.commons.pure.atira.dk"
             xmlns:v1="v1.publication-import.base-uk.pure.atira.dk">
<v1:book id="1" subType="book">
    <v1:peerReviewed>true</v1:peerReviewed>
    <v1:publicationCategory>scientific</v1:publicationCategory>
    <v1:publicationStatus>published</v1:publicationStatus>
    <v1:language>fi</v1:language>
    <v1:title>
        <commons:text>Introduction to scientific reduction</commons:text>
    </v1:title>
    <v1:abstract/>
    <v1:persons>
        <v1:author>
            <v1:role>author</v1:role>
            <v1:person>
                <v1:firstName>Jane</v1:firstName>
                <v1:lastName>Smith</v1:lastName>
            </v1:person>
        </v1:author>
    </v1:persons>
    <v1:organisations>
        <v1:organisation id="2250500"/>
    </v1:organisations>
    <v1:owner id="2250500"/>
    <v1:publicationDate>
     <commons:year>2013</commons:year>
  </v1:publicationDate>
    <v1:visibility>Public</v1:visibility>
    <v1:numberOfPages>2</v1:numberOfPages>
</v1:book>
<v1:book id="1" subType="book">
    <v1:persons>
        <v1:author>
            <v1:role>author</v1:role>
            <v1:person>
                <v1:firstName>John</v1:firstName>
                <v1:lastName>Doe</v1:lastName>
            </v1:person>
        </v1:author>
    </v1:persons>
    <v1:organisations>
        <v1:organisation id="220300"/>
    </v1:organisations>
    </v1:book>
</publications>

我到目前为止的XSLT是这样的:

<?xml version="1.0"?>
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:commons="v3.commons.pure.atira.dk"
xmlns:v1="v1.publication-import.base-uk.pure.atira.dk"
exclude-result-prefixes="xsi xs"
version="2.0">

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

<xsl:template match="/">
<v1:publications>
  <xsl:for-each-group select="/v1:publications/v1:book" group-by="@id">
    <xsl:for-each-group select="current-group()" group-by="if(@Key) then @Key else 'no key'">
    <v1:book>  
        <!-- Copy attributes off the *first* GroupData element in the group -->
        <xsl:copy-of select="current-group()[1]/@*"/>

        <!-- Copy ItemData children from *all* GroupData elements in the group -->

         <xsl:copy-of select="current-group()/*" />

      </v1:book>
    </xsl:for-each-group>
  </xsl:for-each-group>
</v1:publications>

问题是,当我想像这样组合它们时,它会在<v1:book>下为重复项(v1:人)创建单独的节点:

<v1:persons>
   <v1:author></v1:author>
   <v1:author></v1:author>
</v1:persons>

<v1:title/>这样的字段我可以事先从XML中轻松删除,因此它们不是问题。

所需的输出应如下所示,我编辑了几个字段(组织ID和所有者ID以更正)。这是正确导入的实际数据。

<?xml version="1.0" encoding="UTF-8"?>
<v1:publications xmlns:commons="v3.commons.pure.atira.dk"
             xmlns:v1="v1.publication-import.base-uk.pure.atira.dk">
<v1:book id="1" subType="book">
    <v1:peerReviewed>true</v1:peerReviewed>
    <v1:publicationCategory>scientific</v1:publicationCategory>
    <v1:publicationStatus>published</v1:publicationStatus>
    <v1:language>fi_FI</v1:language>
    <v1:title>
        <commons:text>Introduction to scientific reduction</commons:text>
    </v1:title>
    <v1:persons>
        <v1:author>
            <v1:role>author</v1:role>
            <v1:person>
                <v1:firstName>Jane</v1:firstName>
                <v1:lastName>Smith</v1:lastName>
            </v1:person>
        </v1:author>
        <v1:author>
            <v1:role>author</v1:role>
            <v1:person>
                <v1:firstName>John</v1:firstName>
                <v1:lastName>Die</v1:lastName>
            </v1:person>
        </v1:author>
    </v1:persons>
    <v1:organisations>
        <v1:organisation id="2250500"/>
        <v1:organisation id="2250300"/>
    </v1:organisations>
    <v1:owner id="2250300"/>
    <v1:publicationDate>
     <commons:year>2013</commons:year>
  </v1:publicationDate>
    <v1:visibility>Public</v1:visibility>
    <v1:numberOfPages>2</v1:numberOfPages>
</v1:book>
</v1:publications>

2 个答案:

答案 0 :(得分:0)

假设所需的输出是

<v1:persons>
    <v1:author>
        <v1:fullName>John Doe</v1:fullName>
    </v1:author>
</v1:persons>

你需要替换<xsl:copy-of>,它使用每个项目的副本模板来制作完美的副本(因此不允许在其中进行更改)。

一般身份模板match="@*|node()将匹配所有内容(请参阅https://stackoverflow.com/a/617611/2564301),但这将由match="v1:author"特定模板覆盖。这只是写出<v1:firstName><v1:lastName>的值,中间只有一个空格。

为了保持一致性,我添加了<xsl:copy>来复制<v1:author>标记本身,再加上<xsl:apply-templates select="@*"/>来复制其所有属性。这样它也可以使用

等元素
<v1:author id='1'>

- 该属性将按预期复制。

<xsl:template match="/">
<v1:publications>
  <xsl:for-each-group select="/v1:publications/v1:book" group-by="@id">
    <xsl:for-each-group select="current-group()" group-by="if(@Key) then @Key else 'no key'">
    <v1:book>  
        <!-- Copy attributes off the *first* GroupData element in the group -->
        <xsl:apply-templates select="current-group()[1]/@*"/>

        <!-- Copy ItemData children from *all* GroupData elements in the group -->
         <xsl:apply-templates select="current-group()/*" />

      </v1:book>
    </xsl:for-each-group>
  </xsl:for-each-group>
</v1:publications>
</xsl:template>

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

<xsl:template match="v1:author">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <v1:fullName>
            <xsl:value-of select="v1:person/v1:firstName" />
            <xsl:text> </xsl:text>
            <xsl:value-of select="v1:person/v1:lastName" />
        </v1:fullName>
    </xsl:copy>
</xsl:template>

这样可以忠实地复制输入,但<v1:persons>部分替换为

  <v1:persons>
     <v1:author id="1">
        <v1:fullName>Jane Smith</v1:fullName>
     </v1:author>
     <v1:author id="2">
        <v1:fullName>Bob Sandurz</v1:fullName>
     </v1:author>
  </v1:persons>

(我为测试添加了第二个名称和属性。)

答案 1 :(得分:0)

就像不同的方法一样,只使用相同的id复制书籍的作者而不连接名字和姓氏 - 遵循XSLT

<?xml version="1.0"?>
<xsl:stylesheet 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:commons="v3.commons.pure.atira.dk"
 xmlns:v1="v1.publication-import.base-uk.pure.atira.dk"
 exclude-result-prefixes="xsi xs"
 version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/>
  <xsl:template match="/">
    <v1:publications>
      <xsl:for-each-group select="/v1:publications/v1:book" group-by="@id">  
        <xsl:apply-templates select="."/>
      </xsl:for-each-group>
    </v1:publications>
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="v1:person">
  <xsl:variable name="id" select="ancestor::v1:book/@id"/>
    <xsl:copy-of select="//v1:person[ancestor::v1:book[@id=$id]]"/>
  </xsl:template>
</xsl:stylesheet>

当应用于您的输入时,XML会生成输出(相关部分)

<v1:persons>
     <v1:author>
        <v1:role>author</v1:role>
        <v1:person>
           <v1:firstName>Jane</v1:firstName>
           <v1:lastName>Smith</v1:lastName>
        </v1:person>
        <v1:person>
           <v1:firstName>John</v1:firstName>
           <v1:lastName>Doe</v1:lastName>
        </v1:person>
     </v1:author>
  </v1:persons>

匹配v1:person的模板会复制具有相同v1:person的图书子项的所有id个节点。
保存了Demo,另外还有一本不同的id第二本书。