XSLT-XPath:用于重新分组元素的每个路径规范 [英] XSLT-XPath: For-each path specification for re-grouping of elements

查看:193
本文介绍了XSLT-XPath:用于重新分组元素的每个路径规范的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我想要转换到另一个结构的XML文档。文档示例如下所示:

 < application> 
< contactPerson>
< name> Dominik< / name>
< countryCode> DE< / countryCode>
< / contactPerson>
< contactPerson>
<名称> Dorothea< / name>
< countryCode> DE< / countryCode>
< / contactPerson>
< contactPerson>
< name> Fiona< / name>
< countryCode> FR< / countryCode>
< / contactPerson>
< contactPerson>
< name> Fabian< / name>
< countryCode> FR< / countryCode>
< / contactPerson>
< contactPerson>
<名称> Florian< / name>
< countryCode> FR< / countryCode>
< / contactPerson>
< contactPerson>
< name> Gabi< / name>
< countryCode> GB< / countryCode>
< / contactPerson>
< contactPerson>
<名称> Gert< / name>
< countryCode> GB< / countryCode>
< / contactPerson>
< / application>

现在我想要按照国家来分组元素,这意味着结果应该如下所示:

 < application> 
< memberState>
< countryCode> De< / countryCode>
< contactPerson>
< name> Dominik< / name>
< / contactPerson>
< contactPerson>
<名称> Dorothea< / name>
< / contactPerson>
< / memberState>
< memberState>
< countryCode> FR< / countryCode>
< contactPerson>
< name> Fiona< / name>
< / contactPerson>
< contactPerson>
< name> Fabian< / name>
< / contactPerson>
< contactPerson>
<名称> Florian< name>
< / contactPerson>
< / memberState>
< memberState>
< countryCode> GB< / countryCode>
< contactPerson>
< name> Gabi< / name>
< / contactPerson>
< contactPerson>
<名称> Gert< / name>
< / contactPerson>
< / memberState>
< / application>

我正在使用XPath for-each模式来选择所有国家,但它不会执行它应该这样做。我的模式如下所示:

 < xsl:template match =/> 
< application>
< xsl:for-each select =/ application / contactPerson / countryCode [not(。= preceding-sibling :: * / application / contactPerson / countryCode)]>
< memberState>
< countryCode>
< xsl:value-of select =。/>
< / countryCode>
< contactPerson>
< name>
< xsl:value-of select =../ name/>
< / name>
< / contactPerson>
< / memberState>
< / xsl:for-each>
< / application>
< / xsl:template>

该错误可能是XPath表达式中的某处不能编译的。我把它改成了以下内容:

 < xsl:for-each select =/ application / contactPerson / countryCode [not(。 =前同辈:: *)]> 

因为我觉得我已经在树的正确位置了。这个解决方案编译,但它并没有给我一个独特的国家列表,我打算使用之前的兄弟姐妹,而是完整的清单。



除此之外,我需要我的问题的解决方案,我会特别感谢帮助理解实际发生在这里。


  1. 有可能给我的第二个解决方案的相对路径,还是我必须给每个完整的路径?
  2. 我是在正确的轨道上作出一个独特的国家代码列表,或者一般


  3. $ b 是否使用XSLT实际实现了解决方案?
  4. 解决方案

    您的XPath表达式几乎是正确的:

     < xsl:for-each 
    select =/ application / contactPerson / countryCode [not(。= preceding-sibling :: *)]>

    不工作的原因是countryCode没有兄弟关系。要找到以前的countryCodes,您需要向上移动一层,然后再移回:

     < xsl:for-each 
    select =/ application / contactPerson / countryCode [not(。= ../preceding-sibling::/countryCode)]\">

    我相信应该成功遍历不同的countryCodes。

    您对模板的修改应该可以工作。您需要另一个循环遍历每个国家/地区的所有人:

     < xsl:template match =/> 
    < application>
    < xsl:for-each select =/ application / contactPerson / countryCode [not(。= .. / preceding-sibling :: * / countryCode)]>
    < memberState>
    < countryCode>
    < xsl:value-of select =。/>
    < / countryCode>
    < xsl:for-each select =/ application / contactPerson [countryCode = current()]>
    < contactPerson>
    < name>
    < xsl:value-of select =name/>
    < / name>
    < / contactPerson>
    < / xsl:for-each>
    < / memberState>
    < / xsl:for-each>
    < / application>
    < / xsl:template>


    I have XML documents which I want to transfer into another structure. An example of a document looks as follows:

    <application>
        <contactPerson>
            <name>Dominik</name>
            <countryCode>DE</countryCode>
        </contactPerson>
        <contactPerson>
            <name>Dorothea</name>
            <countryCode>DE</countryCode>
        </contactPerson>
        <contactPerson>
            <name>Fiona</name>
            <countryCode>FR</countryCode>
        </contactPerson>
        <contactPerson>
            <name>Fabian</name>
            <countryCode>FR</countryCode>
        </contactPerson>
        <contactPerson>
            <name>Florian</name>
            <countryCode>FR</countryCode>
        </contactPerson>
        <contactPerson>
            <name>Gabi</name>
            <countryCode>GB</countryCode>
        </contactPerson>
        <contactPerson>
            <name>Gert</name>
            <countryCode>GB</countryCode>
        </contactPerson>
    </application>
    

    Now what I want to do is group the elements by country, meaning the result should look like this:

    <application>
        <memberState>
            <countryCode>De</countryCode>
            <contactPerson>
                <name>Dominik</name>
            </contactPerson>
            <contactPerson>
                <name>Dorothea</name>
            </contactPerson>
        </memberState>
        <memberState>
            <countryCode>FR</countryCode>
            <contactPerson>
                <name>Fiona</name>
            </contactPerson>
            <contactPerson>
                <name>Fabian</name>
            </contactPerson>
            <contactPerson>
                <name>Florian<name>
            </contactPerson>
        </memberState>
        <memberState>
            <countryCode>GB</countryCode>
            <contactPerson>
                <name>Gabi</name>
            </contactPerson>
            <contactPerson>
                <name>Gert</name>
            </contactPerson>
        </memberState>
    </application>
    

    I am using an XPath for-each pattern to select all countries, but it doesn't do what it is supposed to do. My pattern looks as follows:

      <xsl:template match="/">
        <application>
          <xsl:for-each select="/application/contactPerson/countryCode[not(.=preceding-sibling::*/application/contactPerson/countryCode)]">
            <memberState>
              <countryCode>
                <xsl:value-of select="."/>
              </countryCode>
              <contactPerson>
                <name>
                  <xsl:value-of select="../name"/>
                </name>
              </contactPerson>
            </memberState>
          </xsl:for-each>
        </application>
      </xsl:template>
    

    The error is probably somewhere in the XPath expression which does not compile. I changed it to the following

    <xsl:for-each select="/application/contactPerson/countryCode[not(.=preceding-sibling::*)]">
    

    because I think I am already at the right position of my tree. This solution compiles, but it doesn't give me a unique list of countries as I intended by using "preceding-sibling" but the complete list instead.

    Besides that I need the solution to my problem, I would be especially thankful for some help on understanding what is actually happening here.

    1. Is it possible to give a relative path as in my second solution or do I have to give the complete path each time?
    2. Am I on the right track for making a unique list of country codes, or would that generally be implemented differently?
    3. Is the solution I am looking for actually implementable with XSLT?

    I appreciate your help very much.

    解决方案

    Your XPath expression was almost correct:

    <xsl:for-each 
        select="/application/contactPerson/countryCode[not(.=preceding-sibling::*)]"> 
    

    The reason it didn't work is that countryCode doesn't have any siblings. To find the previous countryCodes, you need to move up one level and then back down:

    <xsl:for-each 
        select="/application/contactPerson/countryCode[not(. = ../preceding-sibling::*/countryCode)]"> 
    

    I believe that should successfully iterate through the distinct countryCodes.

    This modification to your template should work. You needed another loop to iterate through all the people for each country:

    <xsl:template match="/">
        <application>
          <xsl:for-each select="/application/contactPerson/countryCode[not(.=../preceding-sibling::*/countryCode)]">
            <memberState>
              <countryCode>
                <xsl:value-of select="."/>
              </countryCode>
              <xsl:for-each select="/application/contactPerson[countryCode = current()]">
              <contactPerson>
                <name>
                  <xsl:value-of select="name"/>
                </name>
              </contactPerson>
              </xsl:for-each>
            </memberState>
          </xsl:for-each>
        </application>
      </xsl:template>
    

    这篇关于XSLT-XPath:用于重新分组元素的每个路径规范的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆