使用xslt将xml结构转换为另一个xml结构

使用xslt将xml结构转换为另一个xml结构,xml,xslt,Xml,Xslt,我有个问题。我有以下源xml文件: 源xml: <Container> <DataHeader> <c id="b" value="TAG" /> <c id="g" value="Info" /> </DataHeader> <Data> <Rows> <r no="1"> <c id="b" value="uid1" uid=

我有个问题。我有以下源xml文件:

源xml:

<Container>
  <DataHeader>
    <c id="b" value="TAG" />
    <c id="g" value="Info" /> 
  </DataHeader>
  <Data>
    <Rows>
      <r no="1">
        <c id="b" value="uid1" uid="T.A.uid1" />
        <c id="g" value="uid1|tag1|attr1|somevalue1" />
      </r>
   <r no="1">
        <c id="b" value="uid1" uid="T.A.uid1" />
        <c id="g" value="uid1|tag1|attr2|somevalue2" />
      </r>
      <r no="2">
        <c id="b" value="uid1" uid="T.A.uid1" />
        <c id="g" value="uid1|tag2|attr3|somevalue3" />
      </r>
    <r no="10">
        <c id="b" value="uid2" uid="T.A.uid2" />
        <c id="g" value="uid2|tag1|attr1|somevalue4" />
      </r>
      <r no="11">
        <c id="b" value="uid2" uid="T.A.uid2" />
        <c id="g" value="uid2|tag2|attr3|somevalue5" />
      </r>
   </Rows>
  </Data>
</Container>
<Container>
 <TestTag>
    <object UID="T.A.uid1" Name="uid1"/>
    <tag1 attr1="somevalue1" attr2="somevalue2"/>
    <tag2 attr3="*somevalue3"/>
 </TestTag>
 <TestTag>
    <Iobject UID="T.A.uid2" Name="uid2"/>
    <tag1 attr1="somevalue4" />
    <tag2 attr3="somevalue5"/>
 </TestTag>
</Container>

id为“g”的元素“c”在源xml中很重要。这是一个具体的字符串,其值由“|”分隔。我们需要这些值来生成目标xml。 id为“b”的元素“c”可用于分隔“uid

值的示例和解释

 <c id="g" value="uid1|tag1|attr1|somevalue1" />
 **uid value** | element node | **attribute** | attribute value
 **uid1** | tag1 | **attr1** |somevalue1

**uid值**|元素节点|**属性**|属性值
**uid1**tag1**attr1**somevalue1
必须将具有相同“uid”的所有元素聚合为一个“TestTag”元素(请参见目标xml)。 需要将具有相同父元素(例如“tag1”)的所有属性(attr1,attr2)添加到1个元素中。 我只能使用xslt(xpath)1.0

转换后的目标xml文件应如下所示

通过xsl转换后的目标xml:

<Container>
  <DataHeader>
    <c id="b" value="TAG" />
    <c id="g" value="Info" /> 
  </DataHeader>
  <Data>
    <Rows>
      <r no="1">
        <c id="b" value="uid1" uid="T.A.uid1" />
        <c id="g" value="uid1|tag1|attr1|somevalue1" />
      </r>
   <r no="1">
        <c id="b" value="uid1" uid="T.A.uid1" />
        <c id="g" value="uid1|tag1|attr2|somevalue2" />
      </r>
      <r no="2">
        <c id="b" value="uid1" uid="T.A.uid1" />
        <c id="g" value="uid1|tag2|attr3|somevalue3" />
      </r>
    <r no="10">
        <c id="b" value="uid2" uid="T.A.uid2" />
        <c id="g" value="uid2|tag1|attr1|somevalue4" />
      </r>
      <r no="11">
        <c id="b" value="uid2" uid="T.A.uid2" />
        <c id="g" value="uid2|tag2|attr3|somevalue5" />
      </r>
   </Rows>
  </Data>
</Container>
<Container>
 <TestTag>
    <object UID="T.A.uid1" Name="uid1"/>
    <tag1 attr1="somevalue1" attr2="somevalue2"/>
    <tag2 attr3="*somevalue3"/>
 </TestTag>
 <TestTag>
    <Iobject UID="T.A.uid2" Name="uid2"/>
    <tag1 attr1="somevalue4" />
    <tag2 attr3="somevalue5"/>
 </TestTag>
</Container>

将源xml转换为目标xml有哪些可能的解决方案?我试过好几种方法,但现在我被卡住了

这并不困难,但令人难以置信,因为大量(但必要)嵌套使用了
substring-before()
substring-after()


生成:

<Container>
  <TestTag>
    <object UID="T.A.uid1" name="uid1" />
    <tag1 attr1="somevalue1" attr2="somevalue2"></tag1>
    <tag2 attr3="somevalue3"></tag2>
  </TestTag>
  <TestTag>
    <object UID="T.A.uid2" name="uid2" />
    <tag1 attr1="somevalue4"></tag1>
    <tag2 attr3="somevalue5"></tag2>
  </TestTag>
</Container>

请注意,这不会注意重复的属性定义。如果您碰巧有
uid1 | tag1 | attr1 | somevalue1
和后来的
uid1 | tag1 | attr1 | othervalue1
,那么您将得到一个属性:
attr1=“othervalue1”
,因为在
中,这两个属性都得到了轮到他们,而后者获胜(即在输出中结束)


这也是可能的,它需要一个更多的键和一个更多的明钦族分组,我将留给读者作为练习。呵呵

+1个不错的第一次提问。欢迎来到堆栈溢出!你好,托马拉克,谢谢你的帮助。你的解决方案很有效。但现在我有另一个问题。在源xml中还有一个DataHeader元素。我们不想匹配id的值,因为这是生成的,并且每次id和值的组合都可能不同。我们的解决方案是使用xsl:key按值获取id。我创建了两个变量来通过值获取id's('b'和'g')。示例:问题在于,在您的示例中,您在xsl:key和模板匹配中的id匹配,而我不能在xsl:key或模板匹配中使用变量。这是不可能的。我们如何通过使用上面的解决方案获得相同的结果,或者我们必须重写整个xslt才能使其工作?@TripleJ:这需要对样式表做一点小的更改。没有什么戏剧性的,尤其是因为代码已经“混乱”了。我已经从固定匹配表达式更改为模板模式,并增加了一个键。看看答案的差别:@Tomalak:谢谢你的快速回复!它起作用了。这段代码在性能方面是否高效?你说的“凌乱”到底是什么意思?@TripleJ:性能应该很好,至少我不知道如何让它更快。我所说的“凌乱”是指你看着它很容易头疼。即使按照XSLT标准,也很难理解。大多数复杂性来自这样一个事实,即数据应该位于单独的属性/元素中,这些属性/元素以分隔字符串的形式混在一起。字符串处理是XSLT(1.0)真正不擅长的事情,如果您有机会更改输入XML,一定要这样做。