2013-11-26 6 views
1

У меня есть 1 большой xml-файл, состоящий из 2 разных xml-файлов. Что я хочу сделать, когда я создаю CSV-файл, я хочу, чтобы иметь возможность захватывать данные из второй части файла, которая соответствует первой части. Я использую a для каждого цикла для прохождения всех данных в первой части файла, а затем вложенного цикла для захвата соответствующих данных. Вот XML макет:Шаблон вызова с параметром и значением вывода - XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<Report_Data> 
    <Report_Entry> 
     <company_id>001</company_id> 
     <dept>TestDept</dept> 
    </Report_Entry> 
    <Report_Entry> 
    </Report_Entry> 
    <Company_Data> 
     <Report_Entry> 
      <code>1</code> 
      <name>Test1</name> 
     </Report_Entry> 
     <Report_Entry> 
      <code>2</code> 
      <name>Test2</name> 
     </Report_Entry> 
    </Company_Data> 
</Report_Data> 

Что я хотел бы в моем CSV должен иметь имя от узла Company_Data вставленного в выходной сразу после company_id.

Вот мой XSL файл (в настоящее время он не работает, он перебирает и выводит N/A для каждого узла данных компании в выходном файле):

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wd="urn:com.workday/bsvc"> 
<xsl:output method="text" encoding="utf-8" media-type="text/plain" /> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="newline" select="'&#x0A;'" /> 
<xsl:variable name="tab" select="'&#x09;'" /> 
<xsl:variable name="comma" select="'&#x2C;'" /> 
<xsl:variable name="padding" select="'        '" /> 

<xsl:variable name="ID" select="concat('COMPANY ID', $padding)" /> 
<xsl:variable name="NAME" select="concat('COMPANY NAME', $padding)" /> 
<xsl:variable name="DEPT" select="concat('DEPARTMENT', $padding)" /> 

<xsl:template match="/"> 
    <xsl:value-of select="$ID"/><xsl:value-of select="$comma"/> 
    <xsl:value-of select="$NAME"/><xsl:value-of select="$comma"/> 
    <xsl:value-of select="$DEPT"/><xsl:value-of select="$comma"/> 

    <xsl:for-each select="/Report_Data/Report_Entry"> 
    <xsl:value-of select="translate(substring(concat(company_id, $padding), 1, string-length($ID)), ',', ' ')" /><xsl:value-of select="$comma"/> 

    <xsl:call-template name="company_name"> 
     <xsl:with-param name="id_number" select="company_id"></xsl:with-param> 
</xsl:call-template> 

    <xsl:value-of select="translate(substring(concat(dept, $padding), 1, string-length($DEPT)), ',', ' ')" /><xsl:value-of select="$comma"/> 
</xsl:for-each> 

</xsl:template> 

<xsl:template name="company_name" match="/wd:Report_Data/wd:Company_Data"> 
<xsl:param name="id_number"></xsl:param> 
<xsl:for-each select="/wd:Report_Entry"> 
    <xsl:if test="contains($id_number, code)"> 
     <xsl:value-of select="/name/text()"/> 
    </xsl:if> 
</xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

Мой результат выглядит следующим образом:

1, TestDept 

Вместо того, чтобы:

1, Test1, TestDept 

Это не выводит значение name. Как я могу отобразить это значение?

Я могу добавить материал, если вам нужна дополнительная информация.

ответ

1

Вам не нужно использовать внутренний xsl: for-each Здесь вы можете найти название компании. Вы можете просто использовать XSL: переменная здесь с определенным параметром, где вы можете поместить ваш «содержит» выражения

<xsl:for-each select="Report_Data/Report_Entry"> 
    <xsl:variable 
     name="company_name" 
     select="/Report_Data/Company_Data/Report_Entry[contains(current()/company_id, code)]/name" /> 

Обратите внимание на использование тока() здесь, что для обеспечения выражение использует company_id текущего Report_Data/Report_Entry элемент, в котором вы находитесь, в отличие от Company_Data/Report_Entry, который вы ищете в выражении.Если бы вы делали то, что делаете сейчас, а именно /Report_Data/Report_Entry/company_id, то это выражение «абсолютное», которое начинается с узла документа верхнего уровня и всегда будет возвращать первый company_id в XML.

Но в любом случае вы могли бы просто вывести эту переменную или использовать xsl: выберите для вывода «NA», вместо этого, если переменная будет пустой (т. Е. Имя компании не было найдено).

Если бы не тот факт, что идентификаторы не совпадают, такой поиск значений обычно лучше обрабатывается ключом. Для того, чтобы посмотреть в Report_Entry его код, который вы бы определить ключ, как так

<xsl:key name="company" match="Company_Data/Report_Entry" use="code" /> 

потом посмотреть его вы могли бы сделать что-то вроде этого ...

<xsl:for-each select="Report_Data/Report_Entry"> 
    <xsl:variable name="company_name" select="key('company', company_id)" /> 

Конечно, это потерпит неудачу в ваш случай, потому что идентификаторы не совсем одинаковы, но, возможно, вы можете просто удалить ведущие нули. Попробуйте это, возможно.

<xsl:for-each select="Report_Data/Report_Entry"> 
    <xsl:variable name="company_name" select="key('company', number(company_id))" /> 
+0

спасибо. Ваш первый метод с использованием переменной работал. – RXC

1

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

В настоящее время ваша таблица стилей будет проходить через каждый company_id элемент, и для каждого из них он находит это будет проходное каждый элемент Company_Data/Report_Entry. Вы видите N/A, потому что для каждого company_id он проверяет каждый файл Company_Data/Report_Entry и выводит N/A для тех, которые не соответствуют текущей company_id. Мне кажется, что вам просто нужно удалить в противном случае (в этом случае вам не нужен выбор, просто if). Обратите внимание, что когда я попробовал запустить таблицу стилей, я получал 001, Test1, N/A, Test1, N/A, немного отличающийся от вашего (но мне пришлось добавить отсутствующий для каждого закрывающего тега).

С точки зрения элементов кода и имени, поскольку вы находитесь в цикле for, фокус смещен к элементу, зацикливаемому на нем (Report_Data/Company_Data/Report_Entry), поэтому вы можете использовать относительные пути, которые будут перемещаться из этого элемента с петлями , Итак, вы можете просто использовать «код» или «имя». Вам даже не нужно «./», так как это дает тот же результат.

Смежные вопросы