如何处理xml数据结构中缩小或增长的节点?

时间:2011-06-24 09:41:42

标签: xml xslt

我是XSLT的新手,但有一些编程经验。我发现有时XSL的工作方式非常奇怪,但却很享受挑战。在

这个阶段我只需要一些建议,指出我正确的方向,这样我就可以自己研究,我所描述的问题甚至没有

发生了,但我确信当我们从'测试'变为'现场'时,我将需要知道如何处理它。目前我正在努力编码

获取值的索引,这对于我知道不会改变的节点工作正常,但有些肯定会这样,我需要替代我的身体

硬编码。

另外,我尝试将全局变量用于我的重复'''和','代码,以使代码更容易阅读,但它们不断出现

范围

(所以他们是本地人?)。看不出我做错了什么,或者在哪里宣布它们。理想情况下,我想在

的开头做这件事

脚本,能够随时随地打电话给他们,但这并不紧急。

例如,目前我正在使用它;

<!-- AHPRA XML CSV Converter Script -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" media-type="text" encoding="UTF-8" indent="no" />
<xsl:strip-space elements="*" />

  <xsl:param name="component"/>

  <xsl:template match="/">
    <xsl:choose>

    <!-- COMPONENT 4 communications -->
    <!-- contactID, mediumCode, areaCode, communicationDetails -->
    <xsl:when test="$component=4">
      <xsl:for-each select="//person">
        <xsl:if test="string-length(concat(
          communications/communication/mediumCode, 
          communications/communication/areaCode, 
          communications/communication/communicationDetails))!=0">
          <xsl:value-of select="concat(
          '&quot;', contactID, '&quot;', ', ', '&quot;', 
          communications/communication[1]/mediumCode, '&quot;', ', ', '&quot;', 
          communications/communication[1]/areaCode, '&quot;', ', ', '&quot;', 
          communications/communication[1]/communicationDetails, '&quot;', '&#xa;', 
          '&quot;', contactID, '&quot;', ', ', '&quot;', 
          communications/communication[2]/mediumCode, '&quot;', ', ', '&quot;', 
          communications/communication[2]/areaCode, '&quot;', ', ', '&quot;', 
          communications/communication[2]/communicationDetails, '&quot;', '&#xa;', 
          '&quot;', contactID, '&quot;', ', ', '&quot;', 
          communications/communication[3]/mediumCode, '&quot;', ', ', '&quot;', 
          communications/communication[3]/areaCode, '&quot;', ', ', '&quot;', 
          communications/communication[3]/communicationDetails, '&quot;', '&#xa;')" />
        </xsl:if>
      </xsl:for-each>
    </xsl:when>

    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

关于此;

<medicare>  
  ...
  <person>
    <contactID>5290001890</contactID>
    <communications>
      <communication>
        <mediumCode>T</mediumCode>
      <areaCode>02</areaCode>
        <communicationDetails>92881781</communicationDetails>
      </communication>
      <communication>
        <mediumCode>E</mediumCode>
        <communicationDetails>rabina.smiley@ekit.com</communicationDetails>
      </communication>
    <communication>
        <mediumCode>M</mediumCode>
        <communicationDetails>04290012333</communicationDetails>
      </communication>
    </communications>
  </person>
  <person>
    <contactID>4400139361</contactID>
    <communications>
      <communication>
        <mediumCode>T</mediumCode>
      <areaCode>07</areaCode>
        <communicationDetails>49281771</communicationDetails>
      </communication>
      <communication>
        <mediumCode>E</mediumCode>
        <communicationDetails>suzanne.jones2@optus.com</communicationDetails>
      </communication>
    <communication>
        <mediumCode>M</mediumCode>
        <communicationDetails>0404009266</communicationDetails>
      </communication>
    </communications>
  </person>
  ...
</medicare> 

要做到这一点;

contactID,mediumCode,areaCode,communicationDetails
"5290001890", "T", "02", "92881781"
"5290001890", "E", "", "rabina.smiley@ekit.com"
"5290001890", "M", "", "04290012333"
"4400139361", "T", "07", "49281771"
"4400139361", "E", "", "suzanne.jones2@optus.com"
"4400139361", "M", "", "0404009266"

但我担心如果我的每日xml文件将更改为<;>

,这将无效
<medicare>  
  ...
  <person>
    <contactID>5290001890</contactID>
    <communications>
       <communication>
        <mediumCode>E</mediumCode>
        <communicationDetails>rabina.smiley@ekit.com</communicationDetails>
      </communication>
    <communication>
        <mediumCode>M</mediumCode>
        <communicationDetails>04290012333</communicationDetails>
      </communication>
    </communications>
  </person>
  <person>
    <contactID>4400139361</contactID>
    <communications>
      <communication>
        <mediumCode>T</mediumCode>
      <areaCode>07</areaCode>
        <communicationDetails>49281771</communicationDetails>
      </communication>
      <communication>
        <mediumCode>E</mediumCode>
        <communicationDetails>suzanne.jones2@optus.com</communicationDetails>
      </communication>
    <communication>
        <mediumCode>M</mediumCode>
        <communicationDetails>0404009266</communicationDetails>
    </communications>
  </person>
  ...
</medicare> 

或者这个;

<medicare>  
  ...
  <person>
    <contactID>5290001890</contactID>
    <communications>
      <communication>
        <mediumCode>T</mediumCode>
    <areaCode>02</areaCode>
        <communicationDetails>92881781</communicationDetails>
      </communication>
      <communication>
        <mediumCode>E</mediumCode>
        <communicationDetails>rabina.smiley@ekit.com</communicationDetails>
      </communication>
    <communication>
        <mediumCode>M</mediumCode>
        <communicationDetails>04290012333</communicationDetails>
      </communication>
      <communication>
        <mediumCode>X</mediumCode>
    <areaCode>XX</areaCode>
        <communicationDetails>XXXX</communicationDetails>
      </communication>
    </communications>
  </person>
  <person>
    <contactID>4400139361</contactID>
    <communications>
      <communication>
        <mediumCode>T</mediumCode>
      <areaCode>07</areaCode>
        <communicationDetails>49281771</communicationDetails>
      </communication>
      <communication>
        <mediumCode>E</mediumCode>
        <communicationDetails>suzanne.jones2@optus.com</communicationDetails>
      </communication>
    <communication>
        <mediumCode>M</mediumCode>
        <communicationDetails>0404009266</communicationDetails>
      </communication>
    </communications>
  </person>
  ...
</medicare> 

3 个答案:

答案 0 :(得分:1)

这使用了push样式,因此它只将模板应用于exsist的节点! 一旦你掌握了xslt就会发现它非常强大!

<!-- AHPRA XML CSV Converter Script -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" media-type="text" encoding="UTF-8" indent="no" />
<xsl:strip-space elements="*" />

  <xsl:param name="component"/>

  <xsl:template match="/">
    <xsl:choose>

    <!-- COMPONENT 4 communications -->
    <!-- contactID, mediumCode, areaCode, communicationDetails -->
    <xsl:when test="$component=4">
        <xsl:apply-templates select="//person/communications/communication" />
    </xsl:when>
    </xsl:choose>
  </xsl:template>
<xsl:template match="person/communications/communication">
                <xsl:value-of select="concat(
          '&quot;', ../../contactID, '&quot;', ', ', '&quot;', 
          mediumCode, '&quot;', ', ', '&quot;', 
          areaCode, '&quot;', ', ', '&quot;', 
          communicationDetails, '&quot;', '&#xa;')"/>
        </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

此转换可完全生成所需结果,而不依赖于任何特定数量的communication元素

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="vComponent" select="4"/>

 <xsl:template match="text()"/>

 <xsl:template match="communication[string-length() > 0]">
  <xsl:if test="$vComponent = 4">
    <xsl:value-of select="concat(
     '&quot;', ../../contactID, '&quot;', ', ', '&quot;',
     mediumCode, '&quot;', ', ', '&quot;',
     areaCode, '&quot;', ', ', '&quot;',
     communicationDetails, '&quot;', '&#xa;'
                                 )" />
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于提供的文档

<medicare>
...   
    <person>
        <contactID>5290001890</contactID>
        <communications>
            <communication>
                <mediumCode>T</mediumCode>
                <areaCode>02</areaCode>
                <communicationDetails>92881781</communicationDetails>
            </communication>
            <communication>
                <mediumCode>E</mediumCode>
                <communicationDetails>rabina.smiley@ekit.com</communicationDetails>
            </communication>
            <communication>
                <mediumCode>M</mediumCode>
                <communicationDetails>04290012333</communicationDetails>
            </communication>
        </communications>
    </person>
    <person>
        <contactID>4400139361</contactID>
        <communications>
            <communication>
                <mediumCode>T</mediumCode>
                <areaCode>07</areaCode>
                <communicationDetails>49281771</communicationDetails>
            </communication>
            <communication>
                <mediumCode>E</mediumCode>
                <communicationDetails>suzanne.jones2@optus.com</communicationDetails>
            </communication>
            <communication>
                <mediumCode>M</mediumCode>
                <communicationDetails>0404009266</communicationDetails>
            </communication>
        </communications>
    </person>
    ... 
</medicare>

产生了想要的正确结果

"5290001890", "T", "02", "92881781"
"5290001890", "E", "", "rabina.smiley@ekit.com"
"5290001890", "M", "", "04290012333"
"4400139361", "T", "07", "49281771"
"4400139361", "E", "", "suzanne.jones2@optus.com"
"4400139361", "M", "", "0404009266"

解释:使用XSLT的基本功能:模板模板匹配 XSLT处理模型

答案 2 :(得分:1)

从您的问题中不太清楚您希望如何处理具有额外/缺失communication元素的节点,但是这个答案假设您希望每个联系人都使用中等代码T,E和M.如果您实际上只是想要输出任何内容,@ Treemonkey的答案将根据给定的输入做得很好。

使用索引当然总是选择第n个通信元素,但您可以使用谓词而不是索引来指定它们。例如:

<xsl:value-of select="concat(
      '&quot;', contactID, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='T']/mediumCode, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='T']/areaCode, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='T']/communicationDetails, '&quot;', '&#xa;', 
      '&quot;', contactID, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='E']/mediumCode, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='E']/areaCode, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='E']/communicationDetails, '&quot;', '&#xa;', 
      '&quot;', contactID, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='M']/mediumCode, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='M']/areaCode, '&quot;', ', ', '&quot;', 
      communications/communication[mediumCode='M']/communicationDetails, '&quot;', '&#xa;')" />

您可以使用带参数的命名模板来分解公共元素:

<xsl:template name="outputline">
  <xsl:param name="mediumcode" />
  <xsl:value-of select="concat(
    '&quot;', contactID, '&quot;', ', ', '&quot;', 
    communications/communication[mediumCode=$mediumcode]/mediumCode, '&quot;', ', ', '&quot;', 
    communications/communication[mediumCode=$mediumcode]/areaCode, '&quot;', ', ', '&quot;', 
    communications/communication[mediumCode=$mediumcode]/communicationDetails, '&quot;', '&#xa;')" />
</xsl:template>

并使用:

<xsl:call-template name="outputline">
  <xsl:with-param name="mediumcode" select="'T'" />
</xsl:call-template>
<xsl:call-template name="outputline">
  <xsl:with-param name="mediumcode" select="'E'" />
</xsl:call-template>
<xsl:call-template name="outputline">
  <xsl:with-param name="mediumcode" select="'M'" />
</xsl:call-template>

代替您的<xsl:value-of>电话。