Как вы справляетесь с сокращением или ростом узлов в структурах данных XML? - PullRequest
1 голос
/ 24 июня 2011

Я очень плохо знаком с XSLT, но имею некоторый опыт программирования.Я нахожу, что XSL иногда работает довольно странно, но мне нравится этот вызов.На

этой стадии мне просто нужен совет, чтобы указать мне правильное направление, чтобы я мог исследовать для себя, и проблема, которую я описываю, еще даже

не возникала, но я 'Я уверен, что это произойдет, когда мы перейдем от «тестирования» к «жизни», поэтому мне нужно знать, как справиться с этим.В настоящее время я жестко кодирую

индексов, чтобы получить значения, и это прекрасно работает для узлов, которые, как я знаю, не изменятся, но некоторые, несомненно, будут, поэтому мне нужна альтернатива моему телу

hardcoding.

Кроме того, я попытался использовать глобальные переменные для моего повторяющегося кода '' 'и', 'ниже, чтобы сделать код легче для чтения, но они продолжали выходить

области видимости (чтобы они были локальными?). Не мог понять, что я делал неправильно, или где их объявить. В идеале я хочу сделать это в начале сценария

и иметь возможность вызывать их в любое время и в любом месте.Я хочу, но это не срочно.

Например, в данный момент я использую это;

<!-- 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 ]

1 голос
/ 24 июня 2011

Это преобразование дает в точности нужный результат, не полагаясь на какое-либо определенное количество 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 .

1 голос
/ 26 июня 2011

Из вашего вопроса не слишком ясно, как бы вы хотели обрабатывать узлы с дополнительными / отсутствующими элементами 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> вызова.

1 голос
/ 24 июня 2011

При этом используется стиль push, поэтому шаблон применяется только к существующим узлам! вы найдете, как только вы справитесь с 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...