Как перебрать неизвестные столбцы в XSLT - PullRequest
1 голос
/ 23 марта 2009

Название в значительной степени говорит обо всем. У меня есть документ XML, который я обрабатываю с помощью XSLT .... но я не знаю, сколько столбцов (полей) в документе XML (поэтому, очевидно, я не знаю их имен). Как определить количество «неизвестных» полей? Кроме того, как я могу прочитать атрибуты, если таковые имеются, для неизвестных полей?

Пример данных ....

<Dataset>
   <Row>
       <UnknownCol1 Msg="HowDoIGetThisMsgAttribute?"/>
       <UnknownCol2 />
       <UnknownCol3 />
   </Row>
</Dataset>

Ответы [ 4 ]

2 голосов
/ 23 марта 2009

Как я могу определить количество есть "неизвестные" поля?

Это выражение XPath :

count(/*/*/*)

вычисляет число элементов, которые являются дочерними для элементов, которые являются дочерними элементами верхнего узла XML-документа - именно то, что требуется в этом случае.

Если у элемента "Row" могут быть дочерние элементы, имя которых не начинается с "UnknownCol",

тогда это выражение XPath предоставляет количество элементов, чье имя начинается с "UnknownCol" и которые являются дочерними элементами элементов, которые являются дочерними элементами верхнего элемента:

count(/*/*/*[starts-with(name(), "UnknownCol")])

Если у верхнего элемента могут быть другие дочерние элементы, отличные от "Row", то выражение XPath, дающее необходимое количество, будет:

count(/*/Row/*[starts-with(name(), "UnknownCol")])

Кроме того, как я могу прочитать атрибуты, если есть, для неизвестных полей?

Зная XPath:)

/*/Row/*[starts-with(name(), "UnknownCol")]/@*

выбирает все атрибуты всех элементов "UnknownCol" {String}

Это выражение XPath дает нам количество этих атрибутов:

  count(/*/Row/*[starts-with(name(), "UnknownCol")]/@*)

Это выражение Xpath дает нам имя k-го такого атрибута ($ ind должно быть установлено в число k):

name( (/*/Row/*[starts-with(name(), "UnknownCol")]/@*)[$ind] )

И, наконец, это выражение XPath создает значение k-го такого атрибута:

string( (/*/Row/*[starts-with(name(), "UnknownCol")]/@*)[$ind] )

Редактировать: ОП отметил, что он полностью не знает имен дочернего элемента .

Исправить несложно: просто удалите предикат из всех выражений:

count(/*/*/*)

count(/*/Row/*)


/*/Row/*/@*


count(/*/Row/*/@*)

name( (/*/Row/*/@*)[$ind] )

string( (/*/Row/*/@*)[$ind] )
2 голосов
/ 23 марта 2009

Есть простые способы обойти эту проблему.

В приведенном вами примере вы можете использовать следующий XPath:

select='/Dataset/Row/*/@Msg'

Если вам нужен более конкретный пример этого, вы можете прояснить свой вопрос о том, что именно вы хотели бы сделать с данными и неизвестными столбцами. Вы копируете это точно? Во что конкретно вы хотите превратить это? У вас есть какие-нибудь ключи, которые вы бы хотели сопоставить?

Такого рода вещи.

1 голос
/ 25 ноября 2010

Это также может помочь кому-то:

Проходя через неизвестные узлы, которые начинаются с () AMT_, и проверяйте, пустой ли из них

XML:

<INCOME_FARMING_OPERATIONS>
<PERSONAL_FARMING>
<IND_SCHEDULE>Y</IND_SCHEDULE>
<DESCRIPTION>FARMING OPERATIONS</DESCRIPTION>
<IDENTIFIER>111111111111</IDENTIFIER>
<AMT_FARM_INC_GROSS>22222222</AMT_FARM_INC_GROSS>
<AMT_FARM_INC_PARTNER></AMT_FARM_INC_PARTNER>
<AMT_BAL_LIVESTOCK>99999999</AMT_BAL_LIVESTOCK>
</PERSONAL_FARMING>
</INCOME_FARMING_OPERATIONS>

1008 * XSLT *

<xsl:variable name ="NodeValueIsEmpty">
<xsl:for-each select ="//INCOME_FARMING_OPERATIONS/PERSONAL_FARMING/*[starts-with(name(),'AMT_')]">
<xsl:if test ="string-length(.)=0">
empty found
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="$IncomeFieldValues"/>

Выход: пусто найдено из-за пустого Вы можете взять это дальше:

<xsl:if test=string-length($NodeValueIsEmpty)>0>
//todo if any of the AMT_???? fields is not set
</xsl:if>
1 голос
/ 24 марта 2009

Вот небольшой пример кода XSLT 1.0, который преобразует ваш ввод в таблицу HTML.

<xsl:template match="Dataset">
  <table>
    <thead>
      <tr>
        <xsl:apply-templates select="Row[1]/*" mode="th" />
      </tr>
    </thead>
    <tbody>
      <xsl:apply-templates select="Row" />
    </tbody>
  </table>
</xsl:template>

<xsl:template match="Row">
  <tr>
    <xsl:apply-templates select="*" mode="td" />
  </tr>
</xsl:template>

<xsl:template match="Row/*" mode="th">
  <th>
    <xsl:value-of select="local-name()" />
  </th>
</xsl:template>

<xsl:template match="Row/*" mode="td">
  <td>
    <xsl:value-of select="@Msg" />
  </td>
</xsl:template>

При применении к этому примеру ввода:

<Dataset>
  <Row>
    <UnknownCol1 Msg="Data_1_1" />
    <UnknownCol2 Msg="Data_1_2" />
    <UnknownCol3 Msg="Data_1_3" />
  </Row>
  <Row>
    <UnknownCol1 />
    <UnknownCol2 Msg="Data_2_2" />
    <UnknownCol3 Msg="" />
  </Row>
</Dataset>

возвращается этот вывод:

<table>
  <thead>
    <tr>
      <th>UnknownCol1</th>
      <th>UnknownCol2</th>
      <th>UnknownCol3</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data_1_1</td>
      <td>Data_1_2</td>
      <td>Data_1_3</td>
    </tr>
    <tr>
      <td></td>
      <td>Data_2_2</td>
      <td></td>
    </tr>
  </tbody>
</table>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...